changed the projects filesystem to use require() instead of loadfile()
currently preparing for a better package manager/installer
This commit is contained in:
495
Basalt/BasaltPackager.lua
Normal file
495
Basalt/BasaltPackager.lua
Normal file
@@ -0,0 +1,495 @@
|
|||||||
|
-- The minify part is fully made by stravant and can be found here: https://github.com/stravant/LuaMinify/blob/master/RobloxPlugin/Minify.lua
|
||||||
|
-- Thanks to him for his awesome work!
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Minify.lua
|
||||||
|
--
|
||||||
|
-- A compilation of all of the neccesary code to Minify a source file, all into one single
|
||||||
|
-- script for usage on Roblox. Needed to deal with Roblox' lack of `require`.
|
||||||
|
--
|
||||||
|
|
||||||
|
--The minify part is also minified, if you're looking for the packaging part, check out the bottom!
|
||||||
|
function lookupify(cd)for dd,__a in pairs(cd)do cd[__a]=true end;return cd end
|
||||||
|
function CountTable(cd)local dd=0;for __a in pairs(cd)do dd=dd+1 end;return dd end
|
||||||
|
function PrintTable(cd,dd)if cd.Print then return cd.Print()end;dd=dd or 0
|
||||||
|
local __a=(CountTable(cd)>1)local a_a=string.rep(' ',dd+1)
|
||||||
|
local b_a="{".. (__a and'\n'or'')
|
||||||
|
for c_a,d_a in pairs(cd)do
|
||||||
|
if type(d_a)~='function'then
|
||||||
|
b_a=b_a.. (__a and a_a or'')
|
||||||
|
if type(c_a)=='number'then elseif type(c_a)=='string'and
|
||||||
|
c_a:match("^[A-Za-z_][A-Za-z0-9_]*$")then b_a=b_a..c_a.." = "elseif
|
||||||
|
type(c_a)=='string'then b_a=b_a.."[\""..c_a.."\"] = "else b_a=b_a.."["..
|
||||||
|
tostring(c_a).."] = "end
|
||||||
|
if type(d_a)=='string'then b_a=b_a.."\""..d_a.."\""elseif type(d_a)==
|
||||||
|
'number'then b_a=b_a..d_a elseif type(d_a)=='table'then b_a=b_a..
|
||||||
|
PrintTable(d_a,dd+ (__a and 1 or 0))else
|
||||||
|
b_a=b_a..tostring(d_a)end;if next(cd,c_a)then b_a=b_a..","end;if __a then b_a=b_a..'\n'end end end;b_a=b_a..
|
||||||
|
(__a and string.rep(' ',dd)or'').."}"return b_a end;local bb=lookupify{' ','\n','\t','\r'}
|
||||||
|
local cb={['\r']='\\r',['\n']='\\n',['\t']='\\t',['"']='\\"',["'"]="\\'"}
|
||||||
|
local db=lookupify{'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'}
|
||||||
|
local _c=lookupify{'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'}
|
||||||
|
local ac=lookupify{'0','1','2','3','4','5','6','7','8','9'}
|
||||||
|
local bc=lookupify{'0','1','2','3','4','5','6','7','8','9','A','a','B','b','C','c','D','d','E','e','F','f'}
|
||||||
|
local cc=lookupify{'+','-','*','/','^','%',',','{','}','[',']','(',')',';','#'}
|
||||||
|
local dc=lookupify{'and','break','do','else','elseif','end','false','for','function','goto','if','in','local','nil','not','or','repeat','return','then','true','until','while'}
|
||||||
|
function LexLua(cd)local dd={}
|
||||||
|
local __a,a_a=pcall(function()local _aa=1;local aaa=1;local baa=1
|
||||||
|
local function caa()local cba=cd:sub(_aa,_aa)if cba=='\n'then baa=1
|
||||||
|
aaa=aaa+1 else baa=baa+1 end;_aa=_aa+1;return cba end
|
||||||
|
local function daa(cba)cba=cba or 0;return cd:sub(_aa+cba,_aa+cba)end;local function _ba(cba)local dba=daa()
|
||||||
|
for i=1,#cba do if dba==cba:sub(i,i)then return caa()end end end;local function aba(cba)
|
||||||
|
return error(">> :"..aaa..":"..
|
||||||
|
baa..": "..cba,0)end
|
||||||
|
local function bba()local cba=_aa
|
||||||
|
if daa()=='['then local dba=0;while
|
||||||
|
daa(dba+1)=='='do dba=dba+1 end
|
||||||
|
if daa(dba+1)=='['then for _=0,dba+1 do caa()end
|
||||||
|
local _ca=_aa
|
||||||
|
while true do if daa()==''then
|
||||||
|
aba("Expected `]"..string.rep('=',dba).."]` near <eof>.",3)end;local cca=true;if daa()==']'then for i=1,dba do if daa(i)~='='then
|
||||||
|
cca=false end end
|
||||||
|
if daa(dba+1)~=']'then cca=false end else cca=false end;if cca then break else
|
||||||
|
caa()end end;local aca=cd:sub(_ca,_aa-1)for i=0,dba+1 do caa()end
|
||||||
|
local bca=cd:sub(cba,_aa-1)return aca,bca else return nil end else return nil end end
|
||||||
|
while true do local cba=''
|
||||||
|
while true do local dca=daa()
|
||||||
|
if bb[dca]then cba=cba..caa()elseif
|
||||||
|
dca=='-'and daa(1)=='-'then caa()caa()cba=cba..'--'local _da,ada=bba()
|
||||||
|
if ada then cba=cba..ada else while daa()~='\n'and
|
||||||
|
daa()~=''do cba=cba..caa()end end else break end end;local dba=aaa;local _ca=baa
|
||||||
|
local aca=":"..aaa..":"..baa..":> "local bca=daa()local cca=nil
|
||||||
|
if bca==''then cca={Type='Eof'}elseif
|
||||||
|
_c[bca]or db[bca]or bca=='_'then local dca=_aa;repeat caa()bca=daa()until not
|
||||||
|
(_c[bca]or db[bca]or ac[bca]or bca=='_')
|
||||||
|
local _da=cd:sub(dca,_aa-1)
|
||||||
|
if dc[_da]then cca={Type='Keyword',Data=_da}else cca={Type='Ident',Data=_da}end elseif ac[bca]or(daa()=='.'and ac[daa(1)])then local dca=_aa
|
||||||
|
if bca=='0'and
|
||||||
|
daa(1)=='x'then caa()caa()while bc[daa()]do caa()end;if _ba('Pp')then
|
||||||
|
_ba('+-')while ac[daa()]do caa()end end else
|
||||||
|
while ac[daa()]do caa()end;if _ba('.')then while ac[daa()]do caa()end end;if _ba('Ee')then
|
||||||
|
_ba('+-')while ac[daa()]do caa()end end end;cca={Type='Number',Data=cd:sub(dca,_aa-1)}elseif bca=='\''or bca==
|
||||||
|
'\"'then local dca=_aa;local _da=caa()local ada=_aa;while true do local dda=caa()
|
||||||
|
if dda=='\\'then caa()elseif
|
||||||
|
dda==_da then break elseif dda==''then aba("Unfinished string near <eof>")end end;local bda=cd:sub(ada,
|
||||||
|
_aa-2)local cda=cd:sub(dca,_aa-1)
|
||||||
|
cca={Type='String',Data=cda,Constant=bda}elseif bca=='['then local dca,_da=bba()
|
||||||
|
if _da then cca={Type='String',Data=_da,Constant=dca}else
|
||||||
|
caa()cca={Type='Symbol',Data='['}end elseif _ba('>=<')then if _ba('=')then cca={Type='Symbol',Data=bca..'='}else
|
||||||
|
cca={Type='Symbol',Data=bca}end elseif _ba('~')then
|
||||||
|
if _ba('=')then
|
||||||
|
cca={Type='Symbol',Data='~='}else aba("Unexpected symbol `~` in source.",2)end elseif _ba('.')then
|
||||||
|
if _ba('.')then if _ba('.')then cca={Type='Symbol',Data='...'}else
|
||||||
|
cca={Type='Symbol',Data='..'}end else cca={Type='Symbol',Data='.'}end elseif _ba(':')then if _ba(':')then cca={Type='Symbol',Data='::'}else
|
||||||
|
cca={Type='Symbol',Data=':'}end elseif cc[bca]then caa()
|
||||||
|
cca={Type='Symbol',Data=bca}else local dca,_da=bba()if dca then cca={Type='String',Data=_da,Constant=dca}else
|
||||||
|
aba("Unexpected Symbol `"..
|
||||||
|
bca.."` in source.",2)end end;cca.LeadingWhite=cba;cca.Line=dba;cca.Char=_ca
|
||||||
|
cca.Print=function()
|
||||||
|
return"<".. (cca.Type..string.rep(' ',7 -#
|
||||||
|
cca.Type))..
|
||||||
|
" ".. (cca.Data or'').." >"end;dd[#dd+1]=cca;if cca.Type=='Eof'then break end end end)if not __a then return false,a_a end;local b_a={}local c_a={}local d_a=1
|
||||||
|
function b_a:Peek(_aa)_aa=_aa or 0;return dd[math.min(
|
||||||
|
#dd,d_a+_aa)]end
|
||||||
|
function b_a:Get()local _aa=dd[d_a]d_a=math.min(d_a+1,#dd)return _aa end;function b_a:Is(_aa)return b_a:Peek().Type==_aa end;function b_a:Save()c_a[
|
||||||
|
#c_a+1]=d_a end
|
||||||
|
function b_a:Commit()c_a[#c_a]=nil end;function b_a:Restore()d_a=c_a[#c_a]c_a[#c_a]=nil end
|
||||||
|
function b_a:ConsumeSymbol(_aa)
|
||||||
|
local aaa=self:Peek()
|
||||||
|
if aaa.Type=='Symbol'then if _aa then
|
||||||
|
if aaa.Data==_aa then self:Get()return true else return nil end else self:Get()return aaa end else return
|
||||||
|
nil end end
|
||||||
|
function b_a:ConsumeKeyword(_aa)local aaa=self:Peek()if
|
||||||
|
aaa.Type=='Keyword'and aaa.Data==_aa then self:Get()return true else return nil end end;function b_a:IsKeyword(_aa)local aaa=b_a:Peek()return
|
||||||
|
aaa.Type=='Keyword'and aaa.Data==_aa end
|
||||||
|
function b_a:IsSymbol(_aa)
|
||||||
|
local aaa=b_a:Peek()return aaa.Type=='Symbol'and aaa.Data==_aa end
|
||||||
|
function b_a:IsEof()return b_a:Peek().Type=='Eof'end;return true,b_a end
|
||||||
|
function ParseLua(cd)local dd,__a=LexLua(cd)if not dd then return false,__a end
|
||||||
|
local function a_a(ada)local bda=">> :"..
|
||||||
|
|
||||||
|
__a:Peek().Line..":"..__a:Peek().Char..": "..ada.."\n"local cda=0
|
||||||
|
for dda in
|
||||||
|
cd:gmatch("[^\n]*\n?")do if dda:sub(-1,-1)=='\n'then dda=dda:sub(1,-2)end;cda=
|
||||||
|
cda+1
|
||||||
|
if cda==__a:Peek().Line then bda=bda..">> `"..
|
||||||
|
dda:gsub('\t',' ').."`\n"for i=1,__a:Peek().Char
|
||||||
|
do local __b=dda:sub(i,i)
|
||||||
|
if __b=='\t'then bda=bda..' 'else bda=bda..' 'end end
|
||||||
|
bda=bda.." ^---"break end end;return bda end;local b_a=0;local c_a={}local d_a={'_','a','b','c','d'}
|
||||||
|
local function _aa(ada)local bda={}bda.Parent=ada
|
||||||
|
bda.LocalList={}bda.LocalMap={}
|
||||||
|
function bda:RenameVars()
|
||||||
|
for cda,dda in pairs(bda.LocalList)do local __b;b_a=0
|
||||||
|
repeat b_a=b_a+1;local a_b=b_a
|
||||||
|
__b=''while a_b>0 do local b_b=a_b%#d_a;a_b=(a_b-b_b)/#d_a
|
||||||
|
__b=__b..d_a[b_b+1]end until
|
||||||
|
not c_a[__b]and
|
||||||
|
not ada:GetLocal(__b)and not bda.LocalMap[__b]dda.Name=__b;bda.LocalMap[__b]=dda end end
|
||||||
|
function bda:GetLocal(cda)local dda=bda.LocalMap[cda]if dda then return dda end;if bda.Parent then
|
||||||
|
local __b=bda.Parent:GetLocal(cda)if __b then return __b end end;return nil end
|
||||||
|
function bda:CreateLocal(cda)local dda={}dda.Scope=bda;dda.Name=cda;dda.CanRename=true;bda.LocalList[#
|
||||||
|
bda.LocalList+1]=dda
|
||||||
|
bda.LocalMap[cda]=dda;return dda end;bda.Print=function()return"<Scope>"end;return bda end;local aaa;local baa
|
||||||
|
local function caa(ada)local bda=_aa(ada)if not __a:ConsumeSymbol('(')then return false,
|
||||||
|
a_a("`(` expected.")end;local cda={}local dda=false
|
||||||
|
while not
|
||||||
|
__a:ConsumeSymbol(')')do
|
||||||
|
if __a:Is('Ident')then
|
||||||
|
local c_b=bda:CreateLocal(__a:Get().Data)cda[#cda+1]=c_b;if not __a:ConsumeSymbol(',')then
|
||||||
|
if
|
||||||
|
__a:ConsumeSymbol(')')then break else return false,a_a("`)` expected.")end end elseif
|
||||||
|
__a:ConsumeSymbol('...')then dda=true
|
||||||
|
if not __a:ConsumeSymbol(')')then return false,
|
||||||
|
a_a("`...` must be the last argument of a function.")end;break else return false,a_a("Argument name or `...` expected")end end;local __b,a_b=baa(bda)if not __b then return false,a_b end;if not
|
||||||
|
__a:ConsumeKeyword('end')then
|
||||||
|
return false,a_a("`end` expected after function body")end;local b_b={}
|
||||||
|
b_b.AstType='Function'b_b.Scope=bda;b_b.Arguments=cda;b_b.Body=a_b;b_b.VarArg=dda;return true,b_b end
|
||||||
|
local function daa(ada)
|
||||||
|
if __a:ConsumeSymbol('(')then local bda,cda=aaa(ada)
|
||||||
|
if not bda then return false,cda end
|
||||||
|
if not __a:ConsumeSymbol(')')then return false,a_a("`)` Expected.")end;cda.ParenCount=(cda.ParenCount or 0)+1;return true,cda elseif
|
||||||
|
__a:Is('Ident')then local bda=__a:Get()local cda=ada:GetLocal(bda.Data)if not cda then
|
||||||
|
c_a[bda.Data]=true end;local dda={}dda.AstType='VarExpr'dda.Name=bda.Data
|
||||||
|
dda.Local=cda;return true,dda else return false,a_a("primary expression expected")end end
|
||||||
|
local function _ba(ada,bda)local cda,dda=daa(ada)if not cda then return false,dda end
|
||||||
|
while true do
|
||||||
|
if __a:IsSymbol('.')or
|
||||||
|
__a:IsSymbol(':')then local __b=__a:Get().Data;if not __a:Is('Ident')then return false,
|
||||||
|
a_a("<Ident> expected.")end;local a_b=__a:Get()
|
||||||
|
local b_b={}b_b.AstType='MemberExpr'b_b.Base=dda;b_b.Indexer=__b;b_b.Ident=a_b;dda=b_b elseif not
|
||||||
|
bda and __a:ConsumeSymbol('[')then local __b,a_b=aaa(ada)if not __b then
|
||||||
|
return false,a_b end;if not __a:ConsumeSymbol(']')then
|
||||||
|
return false,a_a("`]` expected.")end;local b_b={}b_b.AstType='IndexExpr'
|
||||||
|
b_b.Base=dda;b_b.Index=a_b;dda=b_b elseif not bda and __a:ConsumeSymbol('(')then local __b={}
|
||||||
|
while not
|
||||||
|
__a:ConsumeSymbol(')')do local b_b,c_b=aaa(ada)if not b_b then return false,c_b end
|
||||||
|
__b[#__b+1]=c_b
|
||||||
|
if not __a:ConsumeSymbol(',')then if __a:ConsumeSymbol(')')then break else return false,
|
||||||
|
a_a("`)` Expected.")end end end;local a_b={}a_b.AstType='CallExpr'a_b.Base=dda;a_b.Arguments=__b;dda=a_b elseif not bda and
|
||||||
|
__a:Is('String')then local __b={}__b.AstType='StringCallExpr'__b.Base=dda
|
||||||
|
__b.Arguments={__a:Get()}dda=__b elseif not bda and __a:IsSymbol('{')then local __b,a_b=aaa(ada)if not __b then
|
||||||
|
return false,a_b end;local b_b={}b_b.AstType='TableCallExpr'b_b.Base=dda
|
||||||
|
b_b.Arguments={a_b}dda=b_b else break end end;return true,dda end
|
||||||
|
local function aba(ada)
|
||||||
|
if __a:Is('Number')then local bda={}bda.AstType='NumberExpr'bda.Value=__a:Get()return
|
||||||
|
true,bda elseif __a:Is('String')then local bda={}bda.AstType='StringExpr'
|
||||||
|
bda.Value=__a:Get()return true,bda elseif __a:ConsumeKeyword('nil')then local bda={}bda.AstType='NilExpr'
|
||||||
|
return true,bda elseif __a:IsKeyword('false')or __a:IsKeyword('true')then local bda={}
|
||||||
|
bda.AstType='BooleanExpr'bda.Value=(__a:Get().Data=='true')return true,bda elseif
|
||||||
|
__a:ConsumeSymbol('...')then local bda={}bda.AstType='DotsExpr'return true,bda elseif __a:ConsumeSymbol('{')then local bda={}
|
||||||
|
bda.AstType='ConstructorExpr'bda.EntryList={}
|
||||||
|
while true do
|
||||||
|
if __a:IsSymbol('[')then __a:Get()local cda,dda=aaa(ada)
|
||||||
|
if not cda then return
|
||||||
|
false,a_a("Key Expression Expected")end
|
||||||
|
if not __a:ConsumeSymbol(']')then return false,a_a("`]` Expected")end
|
||||||
|
if not __a:ConsumeSymbol('=')then return false,a_a("`=` Expected")end;local __b,a_b=aaa(ada)if not __b then
|
||||||
|
return false,a_a("Value Expression Expected")end
|
||||||
|
bda.EntryList[#bda.EntryList+1]={Type='Key',Key=dda,Value=a_b}elseif __a:Is('Ident')then local cda=__a:Peek(1)
|
||||||
|
if
|
||||||
|
cda.Type=='Symbol'and cda.Data=='='then local dda=__a:Get()if not __a:ConsumeSymbol('=')then
|
||||||
|
return false,a_a("`=` Expected")end;local __b,a_b=aaa(ada)if not __b then return false,
|
||||||
|
a_a("Value Expression Expected")end
|
||||||
|
bda.EntryList[
|
||||||
|
#bda.EntryList+1]={Type='KeyString',Key=dda.Data,Value=a_b}else local dda,__b=aaa(ada)
|
||||||
|
if not dda then return false,a_a("Value Exected")end
|
||||||
|
bda.EntryList[#bda.EntryList+1]={Type='Value',Value=__b}end elseif __a:ConsumeSymbol('}')then break else local cda,dda=aaa(ada)
|
||||||
|
bda.EntryList[#bda.EntryList+1]={Type='Value',Value=dda}if not cda then return false,a_a("Value Expected")end end
|
||||||
|
if __a:ConsumeSymbol(';')or __a:ConsumeSymbol(',')then elseif
|
||||||
|
__a:ConsumeSymbol('}')then break else return false,a_a("`}` or table entry Expected")end end;return true,bda elseif __a:ConsumeKeyword('function')then local bda,cda=caa(ada)if not bda then
|
||||||
|
return false,cda end;cda.IsLocal=true;return true,cda else return _ba(ada)end end;local bba=lookupify{'-','not','#'}local cba=8
|
||||||
|
local dba={['+']={6,6},['-']={6,6},['%']={7,7},['/']={7,7},['*']={7,7},['^']={10,9},['..']={5,4},['==']={3,3},['<']={3,3},['<=']={3,3},['~=']={3,3},['>']={3,3},['>=']={3,3},['and']={2,2},['or']={1,1}}
|
||||||
|
local function _ca(ada,bda)local cda,dda
|
||||||
|
if bba[__a:Peek().Data]then local __b=__a:Get().Data
|
||||||
|
cda,dda=_ca(ada,cba)if not cda then return false,dda end;local a_b={}a_b.AstType='UnopExpr'
|
||||||
|
a_b.Rhs=dda;a_b.Op=__b;dda=a_b else cda,dda=aba(ada)if not cda then return false,dda end end
|
||||||
|
while true do local __b=dba[__a:Peek().Data]
|
||||||
|
if __b and __b[1]>bda then
|
||||||
|
local a_b=__a:Get().Data;local b_b,c_b=_ca(ada,__b[2])if not b_b then return false,c_b end;local d_b={}
|
||||||
|
d_b.AstType='BinopExpr'd_b.Lhs=dda;d_b.Op=a_b;d_b.Rhs=c_b;dda=d_b else break end end;return true,dda end;aaa=function(ada)return _ca(ada,0)end
|
||||||
|
local function aca(ada)local bda=nil
|
||||||
|
if
|
||||||
|
__a:ConsumeKeyword('if')then local cda={}cda.AstType='IfStatement'cda.Clauses={}
|
||||||
|
repeat local dda,__b=aaa(ada)if not dda then
|
||||||
|
return false,__b end;if not __a:ConsumeKeyword('then')then return false,
|
||||||
|
a_a("`then` expected.")end
|
||||||
|
local a_b,b_b=baa(ada)if not a_b then return false,b_b end
|
||||||
|
cda.Clauses[#cda.Clauses+1]={Condition=__b,Body=b_b}until not __a:ConsumeKeyword('elseif')
|
||||||
|
if __a:ConsumeKeyword('else')then local dda,__b=baa(ada)
|
||||||
|
if not dda then return false,__b end;cda.Clauses[#cda.Clauses+1]={Body=__b}end;if not __a:ConsumeKeyword('end')then
|
||||||
|
return false,a_a("`end` expected.")end;bda=cda elseif __a:ConsumeKeyword('while')then
|
||||||
|
local cda={}cda.AstType='WhileStatement'local dda,__b=aaa(ada)
|
||||||
|
if not dda then return false,__b end;if not __a:ConsumeKeyword('do')then
|
||||||
|
return false,a_a("`do` expected.")end;local a_b,b_b=baa(ada)
|
||||||
|
if not a_b then return false,b_b end;if not __a:ConsumeKeyword('end')then
|
||||||
|
return false,a_a("`end` expected.")end;cda.Condition=__b;cda.Body=b_b;bda=cda elseif
|
||||||
|
__a:ConsumeKeyword('do')then local cda,dda=baa(ada)if not cda then return false,dda end
|
||||||
|
if not
|
||||||
|
__a:ConsumeKeyword('end')then return false,a_a("`end` expected.")end;local __b={}__b.AstType='DoStatement'__b.Body=dda;bda=__b elseif
|
||||||
|
__a:ConsumeKeyword('for')then
|
||||||
|
if not __a:Is('Ident')then return false,a_a("<ident> expected.")end;local cda=__a:Get()
|
||||||
|
if __a:ConsumeSymbol('=')then local dda=_aa(ada)
|
||||||
|
local __b=dda:CreateLocal(cda.Data)local a_b,b_b=aaa(ada)if not a_b then return false,b_b end
|
||||||
|
if not
|
||||||
|
__a:ConsumeSymbol(',')then return false,a_a("`,` Expected")end;local c_b,d_b=aaa(ada)if not c_b then return false,d_b end;local _ab,aab
|
||||||
|
if
|
||||||
|
__a:ConsumeSymbol(',')then _ab,aab=aaa(ada)if not _ab then return false,aab end end;if not __a:ConsumeKeyword('do')then
|
||||||
|
return false,a_a("`do` expected")end;local bab,cab=baa(dda)
|
||||||
|
if not bab then return false,cab end;if not __a:ConsumeKeyword('end')then
|
||||||
|
return false,a_a("`end` expected")end;local dab={}
|
||||||
|
dab.AstType='NumericForStatement'dab.Scope=dda;dab.Variable=__b;dab.Start=b_b;dab.End=d_b;dab.Step=aab
|
||||||
|
dab.Body=cab;bda=dab else local dda=_aa(ada)
|
||||||
|
local __b={dda:CreateLocal(cda.Data)}
|
||||||
|
while __a:ConsumeSymbol(',')do if not __a:Is('Ident')then return false,
|
||||||
|
a_a("for variable expected.")end
|
||||||
|
__b[#__b+1]=dda:CreateLocal(__a:Get().Data)end;if not __a:ConsumeKeyword('in')then
|
||||||
|
return false,a_a("`in` expected.")end;local a_b={}local b_b,c_b=aaa(ada)if not b_b then
|
||||||
|
return false,c_b end;a_b[#a_b+1]=c_b
|
||||||
|
while __a:ConsumeSymbol(',')do
|
||||||
|
local bab,cab=aaa(ada)if not bab then return false,cab end;a_b[#a_b+1]=cab end;if not __a:ConsumeKeyword('do')then
|
||||||
|
return false,a_a("`do` expected.")end;local d_b,_ab=baa(dda)
|
||||||
|
if not d_b then return false,_ab end;if not __a:ConsumeKeyword('end')then
|
||||||
|
return false,a_a("`end` expected.")end;local aab={}
|
||||||
|
aab.AstType='GenericForStatement'aab.Scope=dda;aab.VariableList=__b;aab.Generators=a_b;aab.Body=_ab;bda=aab end elseif __a:ConsumeKeyword('repeat')then local cda,dda=baa(ada)
|
||||||
|
if not cda then return false,dda end;if not __a:ConsumeKeyword('until')then
|
||||||
|
return false,a_a("`until` expected.")end;local __b,a_b=aaa(ada)
|
||||||
|
if not __b then return false,a_b end;local b_b={}b_b.AstType='RepeatStatement'b_b.Condition=a_b;b_b.Body=dda;bda=b_b elseif
|
||||||
|
__a:ConsumeKeyword('function')then if not __a:Is('Ident')then
|
||||||
|
return false,a_a("Function name expected")end;local cda,dda=_ba(ada,true)if not cda then
|
||||||
|
return false,dda end;local __b,a_b=caa(ada)if not __b then return false,a_b end
|
||||||
|
a_b.IsLocal=false;a_b.Name=dda;bda=a_b elseif __a:ConsumeKeyword('local')then
|
||||||
|
if __a:Is('Ident')then
|
||||||
|
local cda={__a:Get().Data}while __a:ConsumeSymbol(',')do if not __a:Is('Ident')then return false,
|
||||||
|
a_a("local var name expected")end
|
||||||
|
cda[#cda+1]=__a:Get().Data end;local dda={}if
|
||||||
|
__a:ConsumeSymbol('=')then
|
||||||
|
repeat local a_b,b_b=aaa(ada)if not a_b then return false,b_b end
|
||||||
|
dda[#dda+1]=b_b until not __a:ConsumeSymbol(',')end;for a_b,b_b in
|
||||||
|
pairs(cda)do cda[a_b]=ada:CreateLocal(b_b)end
|
||||||
|
local __b={}__b.AstType='LocalStatement'__b.LocalList=cda;__b.InitList=dda;bda=__b elseif
|
||||||
|
__a:ConsumeKeyword('function')then if not __a:Is('Ident')then
|
||||||
|
return false,a_a("Function name expected")end;local cda=__a:Get().Data
|
||||||
|
local dda=ada:CreateLocal(cda)local __b,a_b=caa(ada)if not __b then return false,a_b end;a_b.Name=dda
|
||||||
|
a_b.IsLocal=true;bda=a_b else
|
||||||
|
return false,a_a("local var or function def expected")end elseif __a:ConsumeSymbol('::')then if not __a:Is('Ident')then return false,
|
||||||
|
a_a('Label name expected')end
|
||||||
|
local cda=__a:Get().Data
|
||||||
|
if not __a:ConsumeSymbol('::')then return false,a_a("`::` expected")end;local dda={}dda.AstType='LabelStatement'dda.Label=cda;bda=dda elseif
|
||||||
|
__a:ConsumeKeyword('return')then local cda={}
|
||||||
|
if not __a:IsKeyword('end')then local __b,a_b=aaa(ada)
|
||||||
|
if __b then cda[1]=a_b;while
|
||||||
|
__a:ConsumeSymbol(',')do local b_b,c_b=aaa(ada)if not b_b then return false,c_b end
|
||||||
|
cda[#cda+1]=c_b end end end;local dda={}dda.AstType='ReturnStatement'dda.Arguments=cda;bda=dda elseif
|
||||||
|
__a:ConsumeKeyword('break')then local cda={}cda.AstType='BreakStatement'bda=cda elseif __a:IsKeyword('goto')then
|
||||||
|
if not
|
||||||
|
__a:Is('Ident')then return false,a_a("Label expected")end;local cda=__a:Get().Data;local dda={}dda.AstType='GotoStatement'
|
||||||
|
dda.Label=cda;bda=dda else local cda,dda=_ba(ada)if not cda then return false,dda end
|
||||||
|
if
|
||||||
|
__a:IsSymbol(',')or __a:IsSymbol('=')then
|
||||||
|
if(dda.ParenCount or 0)>0 then return false,
|
||||||
|
a_a("Can not assign to parenthesized expression, is not an lvalue")end;local __b={dda}
|
||||||
|
while __a:ConsumeSymbol(',')do local _ab,aab=_ba(ada)
|
||||||
|
if not _ab then return false,aab end;__b[#__b+1]=aab end
|
||||||
|
if not __a:ConsumeSymbol('=')then return false,a_a("`=` Expected.")end;local a_b={}local b_b,c_b=aaa(ada)if not b_b then return false,c_b end;a_b[1]=c_b;while
|
||||||
|
__a:ConsumeSymbol(',')do local _ab,aab=aaa(ada)if not _ab then return false,aab end
|
||||||
|
a_b[#a_b+1]=aab end;local d_b={}
|
||||||
|
d_b.AstType='AssignmentStatement'd_b.Lhs=__b;d_b.Rhs=a_b;bda=d_b elseif
|
||||||
|
dda.AstType=='CallExpr'or
|
||||||
|
dda.AstType=='TableCallExpr'or dda.AstType=='StringCallExpr'then local __b={}__b.AstType='CallStatement'__b.Expression=dda;bda=__b else return false,
|
||||||
|
a_a("Assignment Statement Expected")end end;bda.HasSemicolon=__a:ConsumeSymbol(';')return true,bda end
|
||||||
|
local bca=lookupify{'end','else','elseif','until'}
|
||||||
|
baa=function(ada)local bda={}bda.Scope=_aa(ada)bda.AstType='Statlist'local cda={}
|
||||||
|
while not
|
||||||
|
bca[__a:Peek().Data]and not __a:IsEof()do
|
||||||
|
local dda,__b=aca(bda.Scope)if not dda then return false,__b end;cda[#cda+1]=__b end;bda.Body=cda;return true,bda end;local function cca()local ada=_aa()return baa(ada)end;local dca,_da=cca()
|
||||||
|
return dca,_da end
|
||||||
|
local _d=lookupify{'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'}
|
||||||
|
local ad=lookupify{'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'}
|
||||||
|
local bd=lookupify{'0','1','2','3','4','5','6','7','8','9'}
|
||||||
|
function Format_Mini(cd)local dd,__a;local a_a=0
|
||||||
|
local function b_a(d_a,_aa,aaa)
|
||||||
|
if a_a>150 then a_a=0;return d_a.."\n".._aa end;aaa=aaa or' 'local baa,caa=d_a:sub(-1,-1),_aa:sub(1,1)
|
||||||
|
if
|
||||||
|
ad[baa]or _d[baa]or baa=='_'then
|
||||||
|
if not
|
||||||
|
(ad[caa]or _d[caa]or caa=='_'or bd[caa])then return d_a.._aa elseif caa=='('then
|
||||||
|
print("==============>>>",baa,caa)return d_a..aaa.._aa else return d_a..aaa.._aa end elseif bd[baa]then
|
||||||
|
if caa=='('then return d_a.._aa else return d_a..aaa.._aa end elseif baa==''then return d_a.._aa else
|
||||||
|
if caa=='('then return d_a..aaa.._aa else return d_a.._aa end end end
|
||||||
|
__a=function(d_a)local _aa=string.rep('(',d_a.ParenCount or 0)
|
||||||
|
if
|
||||||
|
d_a.AstType=='VarExpr'then if d_a.Local then _aa=_aa..d_a.Local.Name else
|
||||||
|
_aa=_aa..d_a.Name end elseif d_a.AstType=='NumberExpr'then _aa=_aa..
|
||||||
|
d_a.Value.Data elseif d_a.AstType=='StringExpr'then
|
||||||
|
_aa=_aa..d_a.Value.Data elseif d_a.AstType=='BooleanExpr'then _aa=_aa..tostring(d_a.Value)elseif
|
||||||
|
d_a.AstType=='NilExpr'then _aa=b_a(_aa,"nil")elseif d_a.AstType=='BinopExpr'then
|
||||||
|
_aa=b_a(_aa,__a(d_a.Lhs))_aa=b_a(_aa,d_a.Op)_aa=b_a(_aa,__a(d_a.Rhs))elseif d_a.AstType==
|
||||||
|
'UnopExpr'then _aa=b_a(_aa,d_a.Op)
|
||||||
|
_aa=b_a(_aa,__a(d_a.Rhs))elseif d_a.AstType=='DotsExpr'then _aa=_aa.."..."elseif d_a.AstType=='CallExpr'then _aa=_aa..
|
||||||
|
__a(d_a.Base)_aa=_aa.."("for i=1,#d_a.Arguments do _aa=_aa..
|
||||||
|
__a(d_a.Arguments[i])
|
||||||
|
if i~=#d_a.Arguments then _aa=_aa..","end end;_aa=_aa..")"elseif d_a.AstType==
|
||||||
|
'TableCallExpr'then _aa=_aa..__a(d_a.Base)_aa=_aa..
|
||||||
|
__a(d_a.Arguments[1])elseif d_a.AstType=='StringCallExpr'then
|
||||||
|
_aa=_aa..__a(d_a.Base)_aa=_aa..d_a.Arguments[1].Data elseif
|
||||||
|
d_a.AstType=='IndexExpr'then
|
||||||
|
_aa=_aa..__a(d_a.Base).."["..__a(d_a.Index).."]"elseif d_a.AstType=='MemberExpr'then _aa=_aa..__a(d_a.Base)..
|
||||||
|
d_a.Indexer..d_a.Ident.Data elseif
|
||||||
|
d_a.AstType=='Function'then d_a.Scope:RenameVars()
|
||||||
|
_aa=_aa.."function("
|
||||||
|
if#d_a.Arguments>0 then for i=1,#d_a.Arguments do
|
||||||
|
_aa=_aa..d_a.Arguments[i].Name
|
||||||
|
if i~=#d_a.Arguments then _aa=_aa..","elseif d_a.VarArg then _aa=_aa..",..."end end elseif
|
||||||
|
d_a.VarArg then _aa=_aa.."..."end;_aa=_aa..")"_aa=b_a(_aa,dd(d_a.Body))
|
||||||
|
_aa=b_a(_aa,"end")elseif d_a.AstType=='ConstructorExpr'then _aa=_aa.."{"
|
||||||
|
for i=1,#d_a.EntryList do
|
||||||
|
local aaa=d_a.EntryList[i]
|
||||||
|
if aaa.Type=='Key'then _aa=_aa.."["..
|
||||||
|
__a(aaa.Key).."]="..__a(aaa.Value)elseif aaa.Type==
|
||||||
|
'Value'then _aa=_aa..__a(aaa.Value)elseif aaa.Type=='KeyString'then
|
||||||
|
_aa=_aa..
|
||||||
|
aaa.Key.."="..__a(aaa.Value)end;if i~=#d_a.EntryList then _aa=_aa..","end end;_aa=_aa.."}"end
|
||||||
|
_aa=_aa..string.rep(')',d_a.ParenCount or 0)a_a=a_a+#_aa;return _aa end
|
||||||
|
local c_a=function(d_a)local _aa=''
|
||||||
|
if d_a.AstType=='AssignmentStatement'then
|
||||||
|
for i=1,#d_a.Lhs do
|
||||||
|
_aa=_aa..__a(d_a.Lhs[i])if i~=#d_a.Lhs then _aa=_aa..","end end;if#d_a.Rhs>0 then _aa=_aa.."="
|
||||||
|
for i=1,#d_a.Rhs do
|
||||||
|
_aa=_aa..__a(d_a.Rhs[i])if i~=#d_a.Rhs then _aa=_aa..","end end end elseif
|
||||||
|
d_a.AstType=='CallStatement'then _aa=__a(d_a.Expression)elseif d_a.AstType=='LocalStatement'then
|
||||||
|
_aa=_aa.."local "
|
||||||
|
for i=1,#d_a.LocalList do _aa=_aa..d_a.LocalList[i].Name;if i~=#
|
||||||
|
d_a.LocalList then _aa=_aa..","end end
|
||||||
|
if#d_a.InitList>0 then _aa=_aa.."="for i=1,#d_a.InitList do _aa=_aa..
|
||||||
|
__a(d_a.InitList[i])
|
||||||
|
if i~=#d_a.InitList then _aa=_aa..","end end end elseif d_a.AstType=='IfStatement'then
|
||||||
|
_aa=b_a("if",__a(d_a.Clauses[1].Condition))_aa=b_a(_aa,"then")
|
||||||
|
_aa=b_a(_aa,dd(d_a.Clauses[1].Body))
|
||||||
|
for i=2,#d_a.Clauses do local aaa=d_a.Clauses[i]
|
||||||
|
if aaa.Condition then
|
||||||
|
_aa=b_a(_aa,"elseif")_aa=b_a(_aa,__a(aaa.Condition))
|
||||||
|
_aa=b_a(_aa,"then")else _aa=b_a(_aa,"else")end;_aa=b_a(_aa,dd(aaa.Body))end;_aa=b_a(_aa,"end")elseif d_a.AstType=='WhileStatement'then
|
||||||
|
_aa=b_a("while",__a(d_a.Condition))_aa=b_a(_aa,"do")_aa=b_a(_aa,dd(d_a.Body))
|
||||||
|
_aa=b_a(_aa,"end")elseif d_a.AstType=='DoStatement'then _aa=b_a(_aa,"do")
|
||||||
|
_aa=b_a(_aa,dd(d_a.Body))_aa=b_a(_aa,"end")elseif d_a.AstType=='ReturnStatement'then _aa="return"
|
||||||
|
for i=1,#d_a.Arguments
|
||||||
|
do _aa=b_a(_aa,__a(d_a.Arguments[i]))if i~=
|
||||||
|
#d_a.Arguments then _aa=_aa..","end end elseif d_a.AstType=='BreakStatement'then _aa="break"elseif d_a.AstType=='RepeatStatement'then
|
||||||
|
_aa="repeat"_aa=b_a(_aa,dd(d_a.Body))_aa=b_a(_aa,"until")
|
||||||
|
_aa=b_a(_aa,__a(d_a.Condition))elseif d_a.AstType=='Function'then d_a.Scope:RenameVars()if d_a.IsLocal then
|
||||||
|
_aa="local"end;_aa=b_a(_aa,"function ")if d_a.IsLocal then
|
||||||
|
_aa=_aa..d_a.Name.Name else _aa=_aa..__a(d_a.Name)end;_aa=
|
||||||
|
_aa.."("
|
||||||
|
if#d_a.Arguments>0 then
|
||||||
|
for i=1,#d_a.Arguments do _aa=_aa..
|
||||||
|
d_a.Arguments[i].Name;if i~=#d_a.Arguments then _aa=_aa..","elseif d_a.VarArg then
|
||||||
|
print("Apply vararg")_aa=_aa..",..."end end elseif d_a.VarArg then _aa=_aa.."..."end;_aa=_aa..")"_aa=b_a(_aa,dd(d_a.Body))
|
||||||
|
_aa=b_a(_aa,"end")elseif d_a.AstType=='GenericForStatement'then d_a.Scope:RenameVars()
|
||||||
|
_aa="for "
|
||||||
|
for i=1,#d_a.VariableList do
|
||||||
|
_aa=_aa..d_a.VariableList[i].Name;if i~=#d_a.VariableList then _aa=_aa..","end end;_aa=_aa.." in"
|
||||||
|
for i=1,#d_a.Generators do
|
||||||
|
_aa=b_a(_aa,__a(d_a.Generators[i]))if i~=#d_a.Generators then _aa=b_a(_aa,',')end end;_aa=b_a(_aa,"do")_aa=b_a(_aa,dd(d_a.Body))
|
||||||
|
_aa=b_a(_aa,"end")elseif d_a.AstType=='NumericForStatement'then _aa="for "_aa=_aa..
|
||||||
|
d_a.Variable.Name.."="_aa=_aa..
|
||||||
|
__a(d_a.Start)..","..__a(d_a.End)if d_a.Step then
|
||||||
|
_aa=_aa..","..__a(d_a.Step)end;_aa=b_a(_aa,"do")
|
||||||
|
_aa=b_a(_aa,dd(d_a.Body))_aa=b_a(_aa,"end")end;a_a=a_a+#_aa;return _aa end
|
||||||
|
dd=function(d_a)local _aa=''d_a.Scope:RenameVars()for aaa,baa in pairs(d_a.Body)do
|
||||||
|
_aa=b_a(_aa,c_a(baa),';')end;return _aa end;cd.Scope:RenameVars()return dd(cd)end
|
||||||
|
local minify = function(cd)local dd,__a=ParseLua(cd)if not dd then return false,__a end
|
||||||
|
return true,Format_Mini(__a)end
|
||||||
|
|
||||||
|
-- Packaging part:
|
||||||
|
local projectPath = "Basalt"
|
||||||
|
local outputFileName = "basalt.lua"
|
||||||
|
|
||||||
|
local projectFiles = {
|
||||||
|
"objects",
|
||||||
|
"libraries",
|
||||||
|
"Frame.lua",
|
||||||
|
"loadObjects.lua",
|
||||||
|
"Object.lua",
|
||||||
|
"theme.lua",
|
||||||
|
}
|
||||||
|
local subDirs = {
|
||||||
|
"objects", "libraries"
|
||||||
|
}
|
||||||
|
local mainFile = "main.lua"
|
||||||
|
local minifyProject = true
|
||||||
|
|
||||||
|
local outputFile = io.open(outputFileName, "w")
|
||||||
|
|
||||||
|
if(outputFile==nil)then
|
||||||
|
error("Can't open file "..outputFileName)
|
||||||
|
end
|
||||||
|
|
||||||
|
outputFile:write([[
|
||||||
|
local project = {}
|
||||||
|
local packaged = true
|
||||||
|
local baseRequire = require
|
||||||
|
local require = function(path)
|
||||||
|
for _,v in pairs(project)do
|
||||||
|
for name,b in pairs(v)do
|
||||||
|
if(name==path)then
|
||||||
|
return b()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return baseRequire(path);
|
||||||
|
end
|
||||||
|
local getProject = function(subDir)
|
||||||
|
if(subDir~=nil)then
|
||||||
|
return project[subDir]
|
||||||
|
end
|
||||||
|
return project
|
||||||
|
end
|
||||||
|
]])
|
||||||
|
|
||||||
|
for k,v in pairs(subDirs)do
|
||||||
|
outputFile:write("project['"..v.."'] = {}")
|
||||||
|
end
|
||||||
|
outputFile:write("project['default'] = {}")
|
||||||
|
|
||||||
|
local function writeNewPackage(subdir, name, path)
|
||||||
|
if not(fs.isDir(path))then
|
||||||
|
outputFile:write("project['"..subdir.."']['"..name.."'] = ".."function(...)")
|
||||||
|
local fileData = io.open(path, "r"):read("*all")
|
||||||
|
if(minifyProject)then
|
||||||
|
local success, data = minify(fileData)
|
||||||
|
if(success)then
|
||||||
|
outputFile:write(data:gsub("]]", "] ]"):gsub("]]", "] ]").."\n")
|
||||||
|
else
|
||||||
|
print("Error: Can't minify "..path)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
outputFile:write(fileData:gsub("]]", "] ]"):gsub("]]", "] ]").."\n")
|
||||||
|
end
|
||||||
|
outputFile:write("end; \n")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for _,v in pairs(projectFiles)do
|
||||||
|
if(fs.isDir(fs.combine(projectPath, v)))then
|
||||||
|
for _,b in pairs(fs.list(fs.combine(projectPath, v)))do
|
||||||
|
writeNewPackage(v, b:gsub(".lua", ""), fs.combine(fs.combine(projectPath, v), b))
|
||||||
|
end
|
||||||
|
else
|
||||||
|
writeNewPackage("default", v:gsub(".lua", ""), fs.combine(projectPath, v))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local main = io.open(fs.combine(projectPath, mainFile), "r"):read("*all")
|
||||||
|
if(minifyProject)then
|
||||||
|
local success,data = minify(main)
|
||||||
|
if(success)then
|
||||||
|
outputFile:write(data)
|
||||||
|
else
|
||||||
|
print("Error: Can't minify "..fs.combine(projectPath, mainFile))
|
||||||
|
end
|
||||||
|
else
|
||||||
|
outputFile:write(main)
|
||||||
|
end
|
||||||
|
|
||||||
|
outputFile:close()
|
||||||
578
Basalt/Frame.lua
Normal file
578
Basalt/Frame.lua
Normal file
@@ -0,0 +1,578 @@
|
|||||||
|
local Object = require("Object")
|
||||||
|
local _OBJECTS = require("loadObjects")
|
||||||
|
|
||||||
|
local BasaltDraw = require("basaltDraw")
|
||||||
|
local theme = require("theme")
|
||||||
|
local utils = require("utils")
|
||||||
|
local rpairs = utils.rpairs
|
||||||
|
|
||||||
|
local sub = string.sub
|
||||||
|
|
||||||
|
return function(name, parent, pTerm, basalt)
|
||||||
|
-- Frame
|
||||||
|
local base = Object(name)
|
||||||
|
local objectType = "Frame"
|
||||||
|
local objects = {}
|
||||||
|
local objZIndex = {}
|
||||||
|
local object = {}
|
||||||
|
local termObject = pTerm or term.current()
|
||||||
|
|
||||||
|
local monSide = ""
|
||||||
|
local isMonitor = false
|
||||||
|
local monitorAttached = false
|
||||||
|
local dragXOffset = 0
|
||||||
|
local dragYOffset = 0
|
||||||
|
|
||||||
|
base:setZIndex(10)
|
||||||
|
|
||||||
|
local basaltDraw = BasaltDraw(termObject)
|
||||||
|
|
||||||
|
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.width, base.height = parent:getSize()
|
||||||
|
base.bgColor = theme.FrameBG
|
||||||
|
base.fgColor = theme.FrameFG
|
||||||
|
else
|
||||||
|
base.width, base.height = termObject.getSize()
|
||||||
|
base.bgColor = theme.basaltBG
|
||||||
|
base.fgColor = theme.basaltFG
|
||||||
|
end
|
||||||
|
|
||||||
|
local function getObject(name)
|
||||||
|
for _, value in pairs(objects) do
|
||||||
|
for _, b in pairs(value) do
|
||||||
|
if (b.name == name) then
|
||||||
|
return value
|
||||||
|
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 key, value in pairs(b) do
|
||||||
|
if (value == obj) then
|
||||||
|
table.remove(objects[a], key)
|
||||||
|
return true;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
object = {
|
||||||
|
barActive = false,
|
||||||
|
barBackground = colors.gray,
|
||||||
|
barTextcolor = colors.black,
|
||||||
|
barText = "New Frame",
|
||||||
|
barTextAlign = "left",
|
||||||
|
isMoveable = false,
|
||||||
|
|
||||||
|
getType = function(self)
|
||||||
|
return objectType
|
||||||
|
end;
|
||||||
|
|
||||||
|
setFocusedObject = function(self, obj)
|
||||||
|
if (basalt.getFocusedObject() ~= nil) then
|
||||||
|
basalt.getFocusedObject():loseFocusHandler()
|
||||||
|
basalt.setFocusedObject(nil)
|
||||||
|
end
|
||||||
|
if(obj~=nil)then
|
||||||
|
basalt.setFocusedObject(obj)
|
||||||
|
obj:getFocusHandler()
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end;
|
||||||
|
|
||||||
|
setSize = function(self, w, h)
|
||||||
|
base.setSize(self, w, h)
|
||||||
|
for _, index in pairs(objZIndex) do
|
||||||
|
if (objects[index] ~= nil) then
|
||||||
|
for _, value in pairs(objects[index]) do
|
||||||
|
if (value.eventHandler ~= nil) then
|
||||||
|
value:sendEvent("basalt_resize", value, self)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end;
|
||||||
|
|
||||||
|
getBasaltInstance = function(self)
|
||||||
|
return basalt
|
||||||
|
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) -- internal
|
||||||
|
return xOffset, yOffset
|
||||||
|
end;
|
||||||
|
|
||||||
|
removeFocusedObject = function(self)
|
||||||
|
if (basalt.getFocusedObject() ~= nil) then
|
||||||
|
basalt.getFocusedObject():loseFocusHandler()
|
||||||
|
end
|
||||||
|
basalt.setFocusedObject(nil)
|
||||||
|
return self
|
||||||
|
end;
|
||||||
|
|
||||||
|
getFocusedObject = function(self)
|
||||||
|
return basalt.getFocusedObject()
|
||||||
|
end;
|
||||||
|
|
||||||
|
setCursor = function(self, _blink, _xCursor, _yCursor, color)
|
||||||
|
if(self.parent~=nil)then
|
||||||
|
local obx, oby = self:getAnchorPosition()
|
||||||
|
self.parent:setCursor(_blink or false, (_xCursor or 0)+obx-1, (_yCursor or 0)+oby-1, color or cursorColor)
|
||||||
|
else
|
||||||
|
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()
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end;
|
||||||
|
|
||||||
|
setMoveable = function(self, moveable)
|
||||||
|
self.isMoveable = moveable or not self.isMoveable
|
||||||
|
self:setVisualChanged()
|
||||||
|
return self;
|
||||||
|
end;
|
||||||
|
|
||||||
|
show = function(self)
|
||||||
|
base.show(self)
|
||||||
|
if(self.parent==nil)then
|
||||||
|
basalt.setActiveFrame(self)
|
||||||
|
if(isMonitor)then
|
||||||
|
basalt.setMonitorFrame(monSide, self)
|
||||||
|
else
|
||||||
|
basalt.setMainFrame(self)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return self;
|
||||||
|
end;
|
||||||
|
|
||||||
|
hide = function (self)
|
||||||
|
base.hide(self)
|
||||||
|
if(self.parent==nil)then
|
||||||
|
if(activeFrame == self)then activeFrame = nil end
|
||||||
|
if(isMonitor)then
|
||||||
|
if(basalt.getMonitorFrame(monSide) == self)then
|
||||||
|
basalt.setActiveFrame(nil)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if(basalt.getMainFrame() == self)then
|
||||||
|
basalt.setMainFrame(nil)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
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;
|
||||||
|
|
||||||
|
setMonitor = function(self, side)
|
||||||
|
if(side~=nil)and(side~=false)then
|
||||||
|
if(peripheral.getType(side)=="monitor")then
|
||||||
|
termObject = peripheral.wrap(side)
|
||||||
|
monitorAttached = true
|
||||||
|
end
|
||||||
|
isMonitor = true
|
||||||
|
else
|
||||||
|
termObject = parentTerminal
|
||||||
|
isMonitor = false
|
||||||
|
if(basalt.getMonitorFrame(monSide)==self)then
|
||||||
|
basalt.setMonitorFrame(monSide, nil)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
basaltDraw = basaltDraw(termObject)
|
||||||
|
monSide = side or nil
|
||||||
|
return self;
|
||||||
|
end;
|
||||||
|
|
||||||
|
getVisualChanged = function(self)
|
||||||
|
local changed = base.getVisualChanged(self)
|
||||||
|
for _, index in pairs(objZIndex) do
|
||||||
|
if (objects[index] ~= nil) then
|
||||||
|
for _, value in pairs(objects[index]) do
|
||||||
|
if (value.getVisualChanged ~= nil and value: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)
|
||||||
|
local focusedObject = basalt.getFocusedObject()
|
||||||
|
if (focusedObject ~= nil) then
|
||||||
|
if(focusedObject~=self)then
|
||||||
|
if (focusedObject.keyHandler ~= nil) then
|
||||||
|
if (focusedObject:keyHandler(event, key)) then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
base.keyHandler(self, event, key)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end;
|
||||||
|
|
||||||
|
backgroundKeyHandler = function(self, event, key)
|
||||||
|
base.backgroundKeyHandler(self, event, key)
|
||||||
|
for _, index in pairs(objZIndex) do
|
||||||
|
if (objects[index] ~= nil) then
|
||||||
|
for _, value in pairs(objects[index]) do
|
||||||
|
if (value.backgroundKeyHandler ~= nil) then
|
||||||
|
value:backgroundKeyHandler(event, key)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
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 _, value in pairs(objects[index]) do
|
||||||
|
if (value.eventHandler ~= nil) then
|
||||||
|
value:eventHandler(event, p1, p2, p3, p4)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if(isMonitor)then
|
||||||
|
if(event == "peripheral")and(p1==monSide)then
|
||||||
|
if(peripheral.getType(monSide)=="monitor")then
|
||||||
|
monitorAttached = true
|
||||||
|
termObject = peripheral.wrap(monSide)
|
||||||
|
basaltDraw = basaltDraw(termObject)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if(event == "peripheral_detach")and(p1==monSide)then
|
||||||
|
monitorAttached = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if (event == "terminate") then
|
||||||
|
termObject.clear()
|
||||||
|
termObject.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 + dragXOffset - (parentX - 1) + xO, y + dragYOffset - (parentY - 1) + yO)
|
||||||
|
end
|
||||||
|
if (event == "mouse_up") then
|
||||||
|
self.drag = false
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
local objX, objY = self:getAbsolutePosition(self:getAnchorPosition())
|
||||||
|
local yOff = false
|
||||||
|
if(objY-1 == y)and(self:getBorder("top"))then
|
||||||
|
y = y+1
|
||||||
|
yOff = true
|
||||||
|
end
|
||||||
|
|
||||||
|
if (base.mouseHandler(self, event, button, x, y)) then
|
||||||
|
local fx, fy = self:getAbsolutePosition(self:getAnchorPosition())
|
||||||
|
fx = fx + xOffset;fy = fy + yOffset;
|
||||||
|
for _, index in pairs(objZIndex) do
|
||||||
|
if (objects[index] ~= nil) then
|
||||||
|
for _, value in rpairs(objects[index]) do
|
||||||
|
if (value.mouseHandler ~= nil) then
|
||||||
|
if (value:mouseHandler(event, button, x, y)) then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if (self.isMoveable) then
|
||||||
|
local fx, fy = self:getAbsolutePosition(self:getAnchorPosition())
|
||||||
|
if (x >= fx) and (x <= fx + self.width - 1) and (y == fy) and (event == "mouse_click") then
|
||||||
|
self.drag = true
|
||||||
|
dragXOffset = fx - x
|
||||||
|
dragYOffset = yOff and 1 or 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if (basalt.getFocusedObject() ~= nil) then
|
||||||
|
basalt.getFocusedObject():loseFocusHandler()
|
||||||
|
basalt.setFocusedObject(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.height) then
|
||||||
|
if (self.parent ~= nil) then
|
||||||
|
local parentX, parentY = self.parent:getAnchorPosition()
|
||||||
|
self.parent:setText(math.max(x + (obx - 1), obx) - (parentX - 1), oby + y - 1 - (parentY - 1), sub(text, math.max(1 - x + 1, 1), math.max(self.width - x + 1,1)))
|
||||||
|
else
|
||||||
|
basaltDraw.setText(math.max(x + (obx - 1), obx), oby + y - 1, sub(text, math.max(1 - x + 1, 1), math.max(self.width - x + 1,1))) -- math.max(self.width - x + 1,1) now, before: self.width - x + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
|
||||||
|
setBG = function(self, x, y, bgCol)
|
||||||
|
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition())
|
||||||
|
if (y >= 1) and (y <= self.height) then
|
||||||
|
if (self.parent ~= nil) then
|
||||||
|
local parentX, parentY = self.parent:getAnchorPosition()
|
||||||
|
self.parent:setBG(math.max(x + (obx - 1), obx) - (parentX - 1), oby + y - 1 - (parentY - 1), sub(bgCol, math.max(1 - x + 1, 1), math.max(self.width - x + 1,1)))
|
||||||
|
else
|
||||||
|
basaltDraw.setBG(math.max(x + (obx - 1), obx), oby + y - 1, sub(bgCol, math.max(1 - x + 1, 1), math.max(self.width - x + 1,1)))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
|
||||||
|
setFG = function(self, x, y, fgCol)
|
||||||
|
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition())
|
||||||
|
if (y >= 1) and (y <= self.height) then
|
||||||
|
if (self.parent ~= nil) then
|
||||||
|
local parentX, parentY = self.parent:getAnchorPosition()
|
||||||
|
self.parent:setFG(math.max(x + (obx - 1), obx) - (parentX - 1), oby + y - 1 - (parentY - 1), sub(fgCol, math.max(1 - x + 1, 1), math.max(self.width - x + 1,1)))
|
||||||
|
else
|
||||||
|
basaltDraw.setFG(math.max(x + (obx - 1), obx), oby + y - 1, sub(fgCol, math.max(1 - x + 1, 1), math.max(self.width - x + 1,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.height) then
|
||||||
|
if (self.parent ~= nil) then
|
||||||
|
local parentX, parentY = self.parent:getAnchorPosition()
|
||||||
|
self.parent:writeText(math.max(x + (obx - 1), obx) - (parentX - 1), oby + y - 1 - (parentY - 1), sub(text, math.max(1 - x + 1, 1), self.width - x + 1), bgCol, fgCol)
|
||||||
|
else
|
||||||
|
basaltDraw.writeText(math.max(x + (obx - 1), obx), oby + y - 1, sub(text, math.max(1 - x + 1, 1), math.max(self.width - x + 1,1)), bgCol, fgCol)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
|
||||||
|
drawBackgroundBox = function(self, x, y, width, height, bgCol)
|
||||||
|
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition())
|
||||||
|
height = (y < 1 and (height + y > self.height and self.height or height + y - 1) or (height + y > self.height and self.height - y + 1 or height))
|
||||||
|
width = (x < 1 and (width + x > self.width and self.width or width + x - 1) or (width + x > self.width and self.width - x + 1 or width))
|
||||||
|
if (self.parent ~= nil) then
|
||||||
|
local parentX, parentY = self.parent:getAnchorPosition()
|
||||||
|
self.parent:drawBackgroundBox(math.max(x + (obx - 1), obx) - (parentX - 1), math.max(y + (oby - 1), oby) - (parentY - 1), width, height, bgCol)
|
||||||
|
else
|
||||||
|
basaltDraw.drawBackgroundBox(math.max(x + (obx - 1), obx), math.max(y + (oby - 1), oby), width, height, bgCol)
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
|
||||||
|
drawTextBox = function(self, x, y, width, height, symbol)
|
||||||
|
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition())
|
||||||
|
height = (y < 1 and (height + y > self.height and self.height or height + y - 1) or (height + y > self.height and self.height - y + 1 or height))
|
||||||
|
width = (x < 1 and (width + x > self.width and self.width or width + x - 1) or (width + x > self.width and self.width - x + 1 or width))
|
||||||
|
if (self.parent ~= nil) then
|
||||||
|
local parentX, parentY = self.parent:getAnchorPosition()
|
||||||
|
self.parent:drawTextBox(math.max(x + (obx - 1), obx) - (parentX - 1), math.max(y + (oby - 1), oby) - (parentY - 1), width, height, symbol:sub(1, 1))
|
||||||
|
else
|
||||||
|
basaltDraw.drawTextBox(math.max(x + (obx - 1), obx), math.max(y + (oby - 1), oby), width, height, symbol:sub(1, 1))
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
|
||||||
|
drawForegroundBox = function(self, x, y, width, height, fgCol)
|
||||||
|
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition())
|
||||||
|
height = (y < 1 and (height + y > self.height and self.height or height + y - 1) or (height + y > self.height and self.height - y + 1 or height))
|
||||||
|
width = (x < 1 and (width + x > self.width and self.width or width + x - 1) or (width + x > self.width and self.width - x + 1 or width))
|
||||||
|
if (self.parent ~= nil) then
|
||||||
|
local parentX, parentY = self.parent:getAnchorPosition()
|
||||||
|
self.parent:drawForegroundBox(math.max(x + (obx - 1), obx) - (parentX - 1), math.max(y + (oby - 1), oby) - (parentY - 1), width, height, fgCol)
|
||||||
|
else
|
||||||
|
basaltDraw.drawForegroundBox(math.max(x + (obx - 1), obx), math.max(y + (oby - 1), oby), width, height, fgCol)
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
|
||||||
|
draw = function(self)
|
||||||
|
if(isMonitor)and not(monitorAttached)then return false end;
|
||||||
|
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
|
||||||
|
if(self.bgColor~=false)then
|
||||||
|
self.parent:drawBackgroundBox(anchx, anchy, self.width, self.height, self.bgColor)
|
||||||
|
self.parent:drawTextBox(anchx, anchy, self.width, self.height, " ")
|
||||||
|
end
|
||||||
|
if(self.bgColor~=false)then self.parent:drawForegroundBox(anchx, anchy, self.width, self.height, self.fgColor) end
|
||||||
|
else
|
||||||
|
if(self.bgColor~=false)then
|
||||||
|
basaltDraw.drawBackgroundBox(obx, oby, self.width, self.height, self.bgColor)
|
||||||
|
basaltDraw.drawTextBox(obx, oby, self.width, self.height, " ")
|
||||||
|
end
|
||||||
|
if(self.fgColor~=false)then basaltDraw.drawForegroundBox(obx, oby, self.width, self.height, self.fgColor) end
|
||||||
|
end
|
||||||
|
termObject.setCursorBlink(false)
|
||||||
|
if (self.barActive) then
|
||||||
|
if (self.parent ~= nil) then
|
||||||
|
self.parent:writeText(anchx, anchy, utils.getTextHorizontalAlign(self.barText, self.width, self.barTextAlign), self.barBackground, self.barTextcolor)
|
||||||
|
else
|
||||||
|
basaltDraw.writeText(obx, oby, utils.getTextHorizontalAlign(self.barText, self.width, self.barTextAlign), self.barBackground, self.barTextcolor)
|
||||||
|
end
|
||||||
|
if(self:getBorder("left"))then
|
||||||
|
if (self.parent ~= nil) then
|
||||||
|
self.parent:drawBackgroundBox(anchx-1, anchy, 1, 1, self.barBackground)
|
||||||
|
if(self.bgColor~=false)then
|
||||||
|
self.parent:drawBackgroundBox(anchx-1, anchy+1, 1, self.height-1, self.bgColor)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if(self:getBorder("top"))then
|
||||||
|
if (self.parent ~= nil) then
|
||||||
|
self.parent:drawBackgroundBox(anchx-1, anchy-1, self.width+1, 1, self.barBackground)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, index in rpairs(objZIndex) do
|
||||||
|
if (objects[index] ~= nil) then
|
||||||
|
for _, value in pairs(objects[index]) do
|
||||||
|
if (value.draw ~= nil) then
|
||||||
|
value:draw()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if (cursorBlink) then
|
||||||
|
termObject.setTextColor(cursorColor)
|
||||||
|
termObject.setCursorPos(xCursor, yCursor)
|
||||||
|
if (self.parent ~= nil) then
|
||||||
|
termObject.setCursorBlink(self:isFocused())
|
||||||
|
else
|
||||||
|
termObject.setCursorBlink(cursorBlink)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
self:setVisualChanged(false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
|
||||||
|
drawUpdate = function(self)
|
||||||
|
if(isMonitor)and not(monitorAttached)then return false end;
|
||||||
|
basaltDraw.update()
|
||||||
|
end;
|
||||||
|
|
||||||
|
addObject = function(self, obj)
|
||||||
|
return addObject(obj)
|
||||||
|
end;
|
||||||
|
|
||||||
|
removeObject = function(self, obj)
|
||||||
|
return removeObject(obj)
|
||||||
|
end;
|
||||||
|
|
||||||
|
getObject = function(self, obj)
|
||||||
|
return getObject(obj)
|
||||||
|
end;
|
||||||
|
|
||||||
|
addFrame = function(self, name)
|
||||||
|
local obj = basalt.newFrame(name, self, nil, basalt)
|
||||||
|
return addObject(obj)
|
||||||
|
end;
|
||||||
|
}
|
||||||
|
for k,v in pairs(_OBJECTS)do
|
||||||
|
object["add"..k] = function(self, name)
|
||||||
|
return addObject(v(name, self))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
setmetatable(object, base)
|
||||||
|
return object
|
||||||
|
end
|
||||||
575
Basalt/Object.lua
Normal file
575
Basalt/Object.lua
Normal file
@@ -0,0 +1,575 @@
|
|||||||
|
local basaltEvent = require("basaltEvent")
|
||||||
|
|
||||||
|
return function(name)
|
||||||
|
-- Base object
|
||||||
|
local objectType = "Object" -- not changeable
|
||||||
|
local value
|
||||||
|
local zIndex = 1
|
||||||
|
local anchor = "topLeft"
|
||||||
|
local ignOffset = false
|
||||||
|
local isVisible = false
|
||||||
|
|
||||||
|
local shadow = false
|
||||||
|
local borderLeft = false
|
||||||
|
local borderTop = false
|
||||||
|
local borderRight = false
|
||||||
|
local borderBottom = false
|
||||||
|
|
||||||
|
local shadowColor = colors.black
|
||||||
|
local borderColor = colors.black
|
||||||
|
|
||||||
|
local visualsChanged = true
|
||||||
|
|
||||||
|
local eventSystem = basaltEvent()
|
||||||
|
|
||||||
|
local object = {
|
||||||
|
x = 1,
|
||||||
|
y = 1,
|
||||||
|
width = 1,
|
||||||
|
height = 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;
|
||||||
|
|
||||||
|
setFocus = function(self)
|
||||||
|
if (self.parent ~= nil) then
|
||||||
|
self.parent:setFocusedObject(self)
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end;
|
||||||
|
|
||||||
|
setZIndex = function(self, index)
|
||||||
|
zIndex = index
|
||||||
|
if (self.parent ~= nil) then
|
||||||
|
self.parent:removeObject(self)
|
||||||
|
self.parent:addObject(self)
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end;
|
||||||
|
|
||||||
|
getZIndex = function(self)
|
||||||
|
return zIndex;
|
||||||
|
end;
|
||||||
|
|
||||||
|
getType = function(self)
|
||||||
|
return objectType
|
||||||
|
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)
|
||||||
|
if (value ~= _value) then
|
||||||
|
value = _value
|
||||||
|
visualsChanged = true
|
||||||
|
self:valueChangedHandler()
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end;
|
||||||
|
|
||||||
|
getValue = function(self)
|
||||||
|
return value
|
||||||
|
end;
|
||||||
|
|
||||||
|
getVisualChanged = function(self)
|
||||||
|
return visualsChanged
|
||||||
|
end;
|
||||||
|
|
||||||
|
setVisualChanged = function(self, change)
|
||||||
|
visualsChanged = change or true
|
||||||
|
if(change == nil)then visualsChanged = true end
|
||||||
|
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 = math.floor(self.x + xPos), math.floor(self.y + yPos)
|
||||||
|
else
|
||||||
|
self.x, self.y = math.floor(xPos), math.floor(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, width, height)
|
||||||
|
self.width, self.height = width, height
|
||||||
|
eventSystem:sendEvent("basalt_resize", self)
|
||||||
|
visualsChanged = true
|
||||||
|
return self
|
||||||
|
end;
|
||||||
|
|
||||||
|
getHeight = function(self)
|
||||||
|
return self.height
|
||||||
|
end;
|
||||||
|
|
||||||
|
getWidth = function(self)
|
||||||
|
return self.width
|
||||||
|
end;
|
||||||
|
|
||||||
|
getSize = function(self)
|
||||||
|
return self.width, self.height
|
||||||
|
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;
|
||||||
|
|
||||||
|
showShadow = function(self, show)
|
||||||
|
shadow = show or (not shadow)
|
||||||
|
return self
|
||||||
|
end;
|
||||||
|
|
||||||
|
setShadow = function(self, color)
|
||||||
|
shadowColor = color
|
||||||
|
return self
|
||||||
|
end;
|
||||||
|
|
||||||
|
isShadowActive = function(self)
|
||||||
|
return shadow;
|
||||||
|
end;
|
||||||
|
|
||||||
|
showBorder = function(self, ...)
|
||||||
|
for _,v in pairs(table.pack(...))do
|
||||||
|
if(v=="left")then
|
||||||
|
borderLeft = true
|
||||||
|
end
|
||||||
|
if(v=="top")then
|
||||||
|
borderTop = true
|
||||||
|
end
|
||||||
|
if(v=="right")then
|
||||||
|
borderRight = true
|
||||||
|
end
|
||||||
|
if(v=="bottom")then
|
||||||
|
borderBottom = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end;
|
||||||
|
|
||||||
|
setBorder = function(self, color)
|
||||||
|
shadowColor = color
|
||||||
|
return self
|
||||||
|
end;
|
||||||
|
|
||||||
|
getBorder = function(self, side)
|
||||||
|
if(side=="left")then
|
||||||
|
return borderLeft;
|
||||||
|
end
|
||||||
|
if(side=="top")then
|
||||||
|
return borderTop;
|
||||||
|
end
|
||||||
|
if(side=="right")then
|
||||||
|
return borderRight;
|
||||||
|
end
|
||||||
|
if(side=="bottom")then
|
||||||
|
return borderBottom;
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
|
||||||
|
draw = function(self)
|
||||||
|
if (isVisible) then
|
||||||
|
if(self.parent~=nil)then
|
||||||
|
local x, y = self:getAnchorPosition()
|
||||||
|
if(shadow)then
|
||||||
|
self.parent:drawBackgroundBox(x+1, y+self.height, self.width, 1, shadowColor)
|
||||||
|
self.parent:drawBackgroundBox(x+self.width, y+1, 1, self.height, shadowColor)
|
||||||
|
self.parent:drawForegroundBox(x+1, y+self.height, self.width, 1, shadowColor)
|
||||||
|
self.parent:drawForegroundBox(x+self.width, y+1, 1, self.height, shadowColor)
|
||||||
|
end
|
||||||
|
if(borderLeft)then
|
||||||
|
self.parent:drawTextBox(x-1, y, 1, self.height, "\149")
|
||||||
|
self.parent:drawForegroundBox(x-1, y, 1, self.height, borderColor)
|
||||||
|
if(self.bgColor~=false)then self.parent:drawBackgroundBox(x-1, y, 1, self.height, self.bgColor) end
|
||||||
|
end
|
||||||
|
if(borderLeft)and(borderTop)then
|
||||||
|
self.parent:drawTextBox(x-1, y-1, 1, 1, "\151")
|
||||||
|
self.parent:drawForegroundBox(x-1, y-1, 1, 1, borderColor)
|
||||||
|
if(self.bgColor~=false)then self.parent:drawBackgroundBox(x-1, y-1, 1, 1, self.bgColor) end
|
||||||
|
end
|
||||||
|
if(borderTop)then
|
||||||
|
self.parent:drawTextBox(x, y-1, self.width, 1, "\131")
|
||||||
|
self.parent:drawForegroundBox(x, y-1, self.width, 1, borderColor)
|
||||||
|
if(self.bgColor~=false)then self.parent:drawBackgroundBox(x, y-1, self.width, 1, self.bgColor) end
|
||||||
|
end
|
||||||
|
if(borderTop)and(borderRight)then
|
||||||
|
self.parent:drawTextBox(x+self.width, y-1, 1, 1, "\149")
|
||||||
|
self.parent:drawForegroundBox(x+self.width, y-1, 1, 1, borderColor)
|
||||||
|
end
|
||||||
|
if(borderRight)then
|
||||||
|
self.parent:drawTextBox(x+self.width, y, 1, self.height, "\149")
|
||||||
|
self.parent:drawForegroundBox(x+self.width, y, 1, self.height, borderColor)
|
||||||
|
end
|
||||||
|
if(borderRight)and(borderBottom)then
|
||||||
|
self.parent:drawTextBox(x+self.width, y+self.height, 1, 1, "\129")
|
||||||
|
self.parent:drawForegroundBox(x+self.width, y+self.height, 1, 1, borderColor)
|
||||||
|
end
|
||||||
|
if(borderBottom)then
|
||||||
|
self.parent:drawTextBox(x, y+self.height, self.width, 1, "\131")
|
||||||
|
self.parent:drawForegroundBox(x, y+self.height, self.width, 1, borderColor)
|
||||||
|
end
|
||||||
|
if(borderBottom)and(borderLeft)then
|
||||||
|
self.parent:drawTextBox(x-1, y+self.height, 1, 1, "\131")
|
||||||
|
self.parent:drawForegroundBox(x-1, y+self.height, 1, 1, borderColor)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
getAbsolutePosition = function(self, x, y)
|
||||||
|
-- relative position to absolute position
|
||||||
|
if (x == nil) or (y == nil) then
|
||||||
|
x, y = self:getAnchorPosition()
|
||||||
|
end
|
||||||
|
|
||||||
|
if (self.parent ~= nil) then
|
||||||
|
local fx, fy = self.parent:getAbsolutePosition(self.parent:getAnchorPosition())
|
||||||
|
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 (anchor == "top") then
|
||||||
|
x = math.floor(self.parent.width/2) + x - 1
|
||||||
|
elseif(anchor == "topRight") then
|
||||||
|
x = self.parent.width + x - 1
|
||||||
|
elseif(anchor == "right") then
|
||||||
|
x = self.parent.width + x - 1
|
||||||
|
y = math.floor(self.parent.height/2) + y - 1
|
||||||
|
elseif(anchor == "bottomRight") then
|
||||||
|
x = self.parent.width + x - 1
|
||||||
|
y = self.parent.height + y - 1
|
||||||
|
elseif(anchor == "bottom") then
|
||||||
|
x = math.floor(self.parent.width/2) + x - 1
|
||||||
|
y = self.parent.height + y - 1
|
||||||
|
elseif(anchor == "bottomLeft") then
|
||||||
|
y = self.parent.height + y - 1
|
||||||
|
elseif(anchor == "left") then
|
||||||
|
y = math.floor(self.parent.height/2) + y - 1
|
||||||
|
elseif(anchor == "center") then
|
||||||
|
x = math.floor(self.parent.width/2) + x - 1
|
||||||
|
y = math.floor(self.parent.height/2) + y - 1
|
||||||
|
end
|
||||||
|
local xO, yO = self:getOffset()
|
||||||
|
if not(ignOffset or ignOff) then
|
||||||
|
return x+xO, y+yO
|
||||||
|
end
|
||||||
|
return x, y
|
||||||
|
end;
|
||||||
|
|
||||||
|
getOffset = function(self)
|
||||||
|
if (self.parent ~= nil) then
|
||||||
|
return self.parent:getFrameOffset()
|
||||||
|
end
|
||||||
|
return 0, 0
|
||||||
|
end;
|
||||||
|
|
||||||
|
ignoreOffset = function(self, ignore)
|
||||||
|
ignOffset = ignore
|
||||||
|
if(ignore==nil)then ignOffset = true end
|
||||||
|
return self
|
||||||
|
end;
|
||||||
|
|
||||||
|
getBaseFrame = function(self)
|
||||||
|
if(self.parent~=nil)then
|
||||||
|
return self.parent:getBaseFrame()
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end;
|
||||||
|
|
||||||
|
setAnchor = function(self, newAnchor)
|
||||||
|
anchor = newAnchor
|
||||||
|
visualsChanged = true
|
||||||
|
return self
|
||||||
|
end;
|
||||||
|
|
||||||
|
getAnchor = function(self)
|
||||||
|
return anchor
|
||||||
|
end;
|
||||||
|
|
||||||
|
onChange = function(self, ...)
|
||||||
|
for _,v in pairs(table.pack(...))do
|
||||||
|
if(type(v)=="function")then
|
||||||
|
self:registerEvent("value_changed", v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end;
|
||||||
|
|
||||||
|
onClick = function(self, ...)
|
||||||
|
for _,v in pairs(table.pack(...))do
|
||||||
|
if(type(v)=="function")then
|
||||||
|
self:registerEvent("mouse_click", v)
|
||||||
|
self:registerEvent("monitor_touch", v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end;
|
||||||
|
|
||||||
|
onClickUp = function(self, ...)
|
||||||
|
for _,v in pairs(table.pack(...))do
|
||||||
|
if(type(v)=="function")then
|
||||||
|
self:registerEvent("mouse_up", v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
onScroll = function(self, ...)
|
||||||
|
for _,v in pairs(table.pack(...))do
|
||||||
|
if(type(v)=="function")then
|
||||||
|
self:registerEvent("mouse_scroll", v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end;
|
||||||
|
|
||||||
|
onDrag = function(self, ...)
|
||||||
|
for _,v in pairs(table.pack(...))do
|
||||||
|
if(type(v)=="function")then
|
||||||
|
self:registerEvent("mouse_drag", v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end;
|
||||||
|
|
||||||
|
onEvent = function(self, ...)
|
||||||
|
for _,v in pairs(table.pack(...))do
|
||||||
|
if(type(v)=="function")then
|
||||||
|
self:registerEvent("custom_event_handler", v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end;
|
||||||
|
|
||||||
|
onKey = function(self, ...)
|
||||||
|
for _,v in pairs(table.pack(...))do
|
||||||
|
if(type(v)=="function")then
|
||||||
|
self:registerEvent("key", v)
|
||||||
|
self:registerEvent("char", v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end;
|
||||||
|
|
||||||
|
onResize = function(self, ...)
|
||||||
|
for _,v in pairs(table.pack(...))do
|
||||||
|
if(type(v)=="function")then
|
||||||
|
self:registerEvent("basalt_resize", v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end;
|
||||||
|
|
||||||
|
onKeyUp = function(self, ...)
|
||||||
|
for _,v in pairs(table.pack(...))do
|
||||||
|
if(type(v)=="function")then
|
||||||
|
self:registerEvent("key_up", v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end;
|
||||||
|
|
||||||
|
onBackgroundKey = function(self, ...)
|
||||||
|
for _,v in pairs(table.pack(...))do
|
||||||
|
if(type(v)=="function")then
|
||||||
|
self:registerEvent("background_key", v)
|
||||||
|
self:registerEvent("background_char", v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end;
|
||||||
|
|
||||||
|
onBackgroundKeyUp = function(self, ...)
|
||||||
|
for _,v in pairs(table.pack(...))do
|
||||||
|
if(type(v)=="function")then
|
||||||
|
self:registerEvent("background_key_up", v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end;
|
||||||
|
|
||||||
|
isFocused = function(self)
|
||||||
|
if (self.parent ~= nil) then
|
||||||
|
return self.parent:getFocusedObject() == self
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end;
|
||||||
|
|
||||||
|
onGetFocus = function(self, ...)
|
||||||
|
for _,v in pairs(table.pack(...))do
|
||||||
|
if(type(v)=="function")then
|
||||||
|
self:registerEvent("get_focus", v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end;
|
||||||
|
|
||||||
|
onLoseFocus = function(self, ...)
|
||||||
|
for _,v in pairs(table.pack(...))do
|
||||||
|
if(type(v)=="function")then
|
||||||
|
self:registerEvent("lose_focus", v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end;
|
||||||
|
|
||||||
|
registerEvent = function(self, event, func)
|
||||||
|
return eventSystem:registerEvent(event, func)
|
||||||
|
end;
|
||||||
|
|
||||||
|
removeEvent = function(self, event, index)
|
||||||
|
return eventSystem:removeEvent(event, index)
|
||||||
|
end;
|
||||||
|
|
||||||
|
sendEvent = function(self, event, ...)
|
||||||
|
return eventSystem:sendEvent(event, self, ...)
|
||||||
|
end;
|
||||||
|
|
||||||
|
mouseHandler = function(self, event, button, x, y)
|
||||||
|
local objX, objY = self:getAbsolutePosition(self:getAnchorPosition())
|
||||||
|
local yOff = false
|
||||||
|
if(objY-1 == y)and(self:getBorder("top"))then
|
||||||
|
y = y+1
|
||||||
|
yOff = true
|
||||||
|
end
|
||||||
|
|
||||||
|
if (objX <= x) and (objX + self.width > x) and (objY <= y) and (objY + self.height > y) and (isVisible) then
|
||||||
|
if (self.parent ~= nil) then
|
||||||
|
self.parent:setFocusedObject(self)
|
||||||
|
end
|
||||||
|
local val = eventSystem:sendEvent(event, self, event, button, x, y)
|
||||||
|
if(val~=nil)then return val end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end;
|
||||||
|
|
||||||
|
keyHandler = function(self, event, key)
|
||||||
|
if (self:isFocused()) then
|
||||||
|
local val = eventSystem:sendEvent(event, self, event, key)
|
||||||
|
if(val~=nil)then return val end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end;
|
||||||
|
|
||||||
|
backgroundKeyHandler = function(self, event, key)
|
||||||
|
local val = eventSystem:sendEvent("background_"..event, self, event, key)
|
||||||
|
if(val~=nil)then return val end
|
||||||
|
return true
|
||||||
|
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)
|
||||||
|
local val = eventSystem:sendEvent("get_focus", self)
|
||||||
|
if(val~=nil)then return val end
|
||||||
|
return true
|
||||||
|
end;
|
||||||
|
|
||||||
|
loseFocusHandler = function(self)
|
||||||
|
local val = eventSystem:sendEvent("lose_focus", self)
|
||||||
|
if(val~=nil)then return val end
|
||||||
|
return true
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
object.__index = object
|
||||||
|
return object
|
||||||
|
end
|
||||||
10
Basalt/init.lua
Normal file
10
Basalt/init.lua
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
local curDir = fs.getDir(table.pack(...)[2]) or ""
|
||||||
|
|
||||||
|
local defaultPath = package.path
|
||||||
|
local format = "%s;/%s/?.lua;/%s/?/init.lua"
|
||||||
|
package.path = string.format(format, package.path, curDir,curDir)..string.format(format, package.path, curDir.."/libraries",curDir.."/libraries")
|
||||||
|
|
||||||
|
local Basalt = require("main")
|
||||||
|
package.path = defaultPath
|
||||||
|
|
||||||
|
return Basalt
|
||||||
184
Basalt/libraries/basaltDraw.lua
Normal file
184
Basalt/libraries/basaltDraw.lua
Normal file
@@ -0,0 +1,184 @@
|
|||||||
|
local tHex = require("tHex")
|
||||||
|
local sub,rep = string.sub,string.rep
|
||||||
|
|
||||||
|
return function(drawTerm)
|
||||||
|
local terminal = drawTerm or term.current()
|
||||||
|
local width, height = terminal.getSize()
|
||||||
|
local cacheT = {}
|
||||||
|
local cacheBG = {}
|
||||||
|
local cacheFG = {}
|
||||||
|
|
||||||
|
local _cacheT = {}
|
||||||
|
local _cacheBG = {}
|
||||||
|
local _cacheFG = {}
|
||||||
|
|
||||||
|
local emptySpaceLine
|
||||||
|
local emptyColorLines = {}
|
||||||
|
|
||||||
|
local function createEmptyLines()
|
||||||
|
emptySpaceLine = rep(" ", width)
|
||||||
|
for n = 0, 15 do
|
||||||
|
local nColor = 2 ^ n
|
||||||
|
local sHex = tHex[nColor]
|
||||||
|
emptyColorLines[nColor] = rep(sHex, width)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
----
|
||||||
|
createEmptyLines()
|
||||||
|
|
||||||
|
local function recreateWindowArray()
|
||||||
|
local emptyText = emptySpaceLine
|
||||||
|
local emptyFG = emptyColorLines[colors.white]
|
||||||
|
local emptyBG = emptyColorLines[colors.black]
|
||||||
|
for currentY = 1, height do
|
||||||
|
cacheT[currentY] = sub(cacheT[currentY] == nil and emptyText or cacheT[currentY] .. emptyText:sub(1, width - cacheT[currentY]:len()), 1, width)
|
||||||
|
cacheFG[currentY] = sub(cacheFG[currentY] == nil and emptyFG or cacheFG[currentY] .. emptyFG:sub(1, width - cacheFG[currentY]:len()), 1, width)
|
||||||
|
cacheBG[currentY] = sub(cacheBG[currentY] == nil and emptyBG or cacheBG[currentY] .. emptyBG:sub(1, width - cacheBG[currentY]:len()), 1, width)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
recreateWindowArray()
|
||||||
|
|
||||||
|
local function setText(x, y, text)
|
||||||
|
if (y >= 1) and (y <= height) then
|
||||||
|
if (x + text:len() > 0) and (x <= width) then
|
||||||
|
local oldCache = cacheT[y]
|
||||||
|
local newCache
|
||||||
|
local nEnd = x + #text - 1
|
||||||
|
|
||||||
|
if (x < 1) then
|
||||||
|
local startN = 1 - x + 1
|
||||||
|
local endN = width - x + 1
|
||||||
|
text = sub(text, startN, endN)
|
||||||
|
elseif (nEnd > width) then
|
||||||
|
local endN = width - x + 1
|
||||||
|
text = sub(text, 1, endN)
|
||||||
|
end
|
||||||
|
|
||||||
|
if (x > 1) then
|
||||||
|
local endN = x - 1
|
||||||
|
newCache = sub(oldCache, 1, endN) .. text
|
||||||
|
else
|
||||||
|
newCache = text
|
||||||
|
end
|
||||||
|
if nEnd < width then
|
||||||
|
newCache = newCache .. sub(oldCache, nEnd + 1, width)
|
||||||
|
end
|
||||||
|
cacheT[y] = newCache
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function setBG(x, y, colorStr)
|
||||||
|
if (y >= 1) and (y <= height) then
|
||||||
|
if (x + colorStr:len() > 0) and (x <= width) then
|
||||||
|
local oldCache = cacheBG[y]
|
||||||
|
local newCache
|
||||||
|
local nEnd = x + #colorStr - 1
|
||||||
|
|
||||||
|
if (x < 1) then
|
||||||
|
colorStr = sub(colorStr, 1 - x + 1, width - x + 1)
|
||||||
|
elseif (nEnd > width) then
|
||||||
|
colorStr = sub(colorStr, 1, width - x + 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
if (x > 1) then
|
||||||
|
newCache = sub(oldCache, 1, x - 1) .. colorStr
|
||||||
|
else
|
||||||
|
newCache = colorStr
|
||||||
|
end
|
||||||
|
if nEnd < width then
|
||||||
|
newCache = newCache .. sub(oldCache, nEnd + 1, width)
|
||||||
|
end
|
||||||
|
cacheBG[y] = newCache
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function setFG(x, y, colorStr)
|
||||||
|
if (y >= 1) and (y <= height) then
|
||||||
|
if (x + colorStr:len() > 0) and (x <= width) then
|
||||||
|
local oldCache = cacheFG[y]
|
||||||
|
local newCache
|
||||||
|
local nEnd = x + #colorStr - 1
|
||||||
|
|
||||||
|
if (x < 1) then
|
||||||
|
local startN = 1 - x + 1
|
||||||
|
local endN = width - x + 1
|
||||||
|
colorStr = sub(colorStr, startN, endN)
|
||||||
|
elseif (nEnd > width) then
|
||||||
|
local endN = width - x + 1
|
||||||
|
colorStr = sub(colorStr, 1, endN)
|
||||||
|
end
|
||||||
|
|
||||||
|
if (x > 1) then
|
||||||
|
local endN = x - 1
|
||||||
|
newCache = sub(oldCache, 1, endN) .. colorStr
|
||||||
|
else
|
||||||
|
newCache = colorStr
|
||||||
|
end
|
||||||
|
if nEnd < width then
|
||||||
|
newCache = newCache .. sub(oldCache, nEnd + 1, width)
|
||||||
|
end
|
||||||
|
cacheFG[y] = newCache
|
||||||
|
end
|
||||||
|
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, width, height, bgCol)
|
||||||
|
for n = 1, height do
|
||||||
|
setBG(x, y + (n - 1), rep(tHex[bgCol], width))
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
drawForegroundBox = function(x, y, width, height, fgCol)
|
||||||
|
for n = 1, height do
|
||||||
|
setFG(x, y + (n - 1) ,rep(tHex[fgCol], width))
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
drawTextBox = function(x, y, width, height, symbol)
|
||||||
|
for n = 1, height do
|
||||||
|
setText(x, y + (n - 1), rep(symbol, width))
|
||||||
|
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, rep(tHex[bgCol], text:len()))
|
||||||
|
setFG(x, y, rep(tHex[fgCol], text:len()))
|
||||||
|
end;
|
||||||
|
|
||||||
|
update = function()
|
||||||
|
local xC, yC = terminal.getCursorPos()
|
||||||
|
local isBlinking = false
|
||||||
|
if (terminal.getCursorBlink ~= nil) then
|
||||||
|
isBlinking = terminal.getCursorBlink()
|
||||||
|
end
|
||||||
|
terminal.setCursorBlink(false)
|
||||||
|
for n = 1, height do
|
||||||
|
terminal.setCursorPos(1, n)
|
||||||
|
terminal.blit(cacheT[n], cacheFG[n], cacheBG[n])
|
||||||
|
end
|
||||||
|
terminal.setBackgroundColor(colors.black)
|
||||||
|
terminal.setCursorBlink(isBlinking)
|
||||||
|
terminal.setCursorPos(xC, yC)
|
||||||
|
end;
|
||||||
|
|
||||||
|
setTerm = function(newTerm)
|
||||||
|
terminal = newTerm;
|
||||||
|
end;
|
||||||
|
}
|
||||||
|
return drawHelper
|
||||||
|
end
|
||||||
35
Basalt/libraries/basaltEvent.lua
Normal file
35
Basalt/libraries/basaltEvent.lua
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
return function()
|
||||||
|
local events = {}
|
||||||
|
local index = {}
|
||||||
|
|
||||||
|
local event = {
|
||||||
|
registerEvent = function(self, _event, func)
|
||||||
|
if (events[_event] == nil) then
|
||||||
|
events[_event] = {}
|
||||||
|
index[_event] = 1
|
||||||
|
end
|
||||||
|
events[_event][index[_event]] = func
|
||||||
|
index[_event] = index[_event] + 1
|
||||||
|
return index[_event] - 1
|
||||||
|
end;
|
||||||
|
|
||||||
|
removeEvent = function(self, _event, index)
|
||||||
|
events[_event][index[_event]] = nil
|
||||||
|
end;
|
||||||
|
|
||||||
|
sendEvent = function(self, _event, ...)
|
||||||
|
local returnValue
|
||||||
|
if (events[_event] ~= nil) then
|
||||||
|
for _, value in pairs(events[_event]) do
|
||||||
|
local val = value(...)
|
||||||
|
if(val==false)then
|
||||||
|
returnValue = val
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return returnValue
|
||||||
|
end;
|
||||||
|
}
|
||||||
|
event.__index = event
|
||||||
|
return event
|
||||||
|
end
|
||||||
137
Basalt/libraries/bigfont.lua
Normal file
137
Basalt/libraries/bigfont.lua
Normal file
File diff suppressed because one or more lines are too long
16
Basalt/libraries/logSystem.lua
Normal file
16
Basalt/libraries/logSystem.lua
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
local logDir = ""
|
||||||
|
local logFileName = "log.txt"
|
||||||
|
|
||||||
|
return {
|
||||||
|
setLogDir = function(dir)
|
||||||
|
logDir = dir
|
||||||
|
end,
|
||||||
|
|
||||||
|
setLogFileName = function(name)
|
||||||
|
logFileName = name
|
||||||
|
end,
|
||||||
|
|
||||||
|
__call = function()
|
||||||
|
--somelogs
|
||||||
|
end
|
||||||
|
}
|
||||||
52
Basalt/libraries/process.lua
Normal file
52
Basalt/libraries/process.lua
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
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({ }, 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
|
||||||
|
|
||||||
|
return process
|
||||||
18
Basalt/libraries/tHex.lua
Normal file
18
Basalt/libraries/tHex.lua
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
return { -- copy paste is a very important feature
|
||||||
|
[colors.white] = "0",
|
||||||
|
[colors.orange] = "1",
|
||||||
|
[colors.magenta] = "2",
|
||||||
|
[colors.lightBlue] = "3",
|
||||||
|
[colors.yellow] = "4",
|
||||||
|
[colors.lime] = "5",
|
||||||
|
[colors.pink] = "6",
|
||||||
|
[colors.gray] = "7",
|
||||||
|
[colors.lightGray] = "8",
|
||||||
|
[colors.cyan] = "9",
|
||||||
|
[colors.purple] = "a",
|
||||||
|
[colors.blue] = "b",
|
||||||
|
[colors.brown] = "c",
|
||||||
|
[colors.green] = "d",
|
||||||
|
[colors.red] = "e",
|
||||||
|
[colors.black] = "f",
|
||||||
|
}
|
||||||
161
Basalt/libraries/utils.lua
Normal file
161
Basalt/libraries/utils.lua
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
return {
|
||||||
|
getTextHorizontalAlign = function(text, width, textAlign, replaceChar)
|
||||||
|
text = string.sub(text, 1, width)
|
||||||
|
local offset = width - string.len(text)
|
||||||
|
if (textAlign == "right") then
|
||||||
|
text = string.rep(replaceChar or " ", offset) .. text
|
||||||
|
elseif (textAlign == "center") then
|
||||||
|
text = string.rep(replaceChar or " ", math.floor(offset / 2)) .. text .. string.rep(replaceChar or " ", math.floor(offset / 2))
|
||||||
|
text = text .. (string.len(text) < width and (replaceChar or " ") or "")
|
||||||
|
else
|
||||||
|
text = text .. string.rep(replaceChar or " ", offset)
|
||||||
|
end
|
||||||
|
return text
|
||||||
|
end,
|
||||||
|
|
||||||
|
getTextVerticalAlign = function(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
|
||||||
|
if(offset<1)then offset=1 end
|
||||||
|
return offset
|
||||||
|
end,
|
||||||
|
|
||||||
|
rpairs = function(t)
|
||||||
|
return function(t, i)
|
||||||
|
i = i - 1
|
||||||
|
if i ~= 0 then
|
||||||
|
return i, t[i]
|
||||||
|
end
|
||||||
|
end, t, #t + 1
|
||||||
|
end,
|
||||||
|
|
||||||
|
-- shrink system is copy pasted (and slightly changed) from blittle by Bomb Bloke: http://www.computercraft.info/forums2/index.php?/topic/25354-cc-176-blittle-api/
|
||||||
|
shrink = function(bLittleData, bgColor)
|
||||||
|
local relations = { [0] = { 8, 4, 3, 6, 5 }, { 4, 14, 8, 7 }, { 6, 10, 8, 7 }, { 9, 11, 8, 0 }, { 1, 14, 8, 0 }, { 13, 12, 8, 0 }, { 2, 10, 8, 0 }, { 15, 8, 10, 11, 12, 14 },
|
||||||
|
{ 0, 7, 1, 9, 2, 13 }, { 3, 11, 8, 7 }, { 2, 6, 7, 15 }, { 9, 3, 7, 15 }, { 13, 5, 7, 15 }, { 5, 12, 8, 7 }, { 1, 4, 7, 15 }, { 7, 10, 11, 12, 14 } }
|
||||||
|
|
||||||
|
local colourNum, exponents, colourChar = {}, {}, {}
|
||||||
|
for i = 0, 15 do
|
||||||
|
exponents[2 ^ i] = i
|
||||||
|
end
|
||||||
|
do
|
||||||
|
local hex = "0123456789abcdef"
|
||||||
|
for i = 1, 16 do
|
||||||
|
colourNum[hex:sub(i, i)] = i - 1
|
||||||
|
colourNum[i - 1] = hex:sub(i, i)
|
||||||
|
colourChar[hex:sub(i, i)] = 2 ^ (i - 1)
|
||||||
|
colourChar[2 ^ (i - 1)] = hex:sub(i, i)
|
||||||
|
|
||||||
|
local thisRel = relations[i - 1]
|
||||||
|
for i = 1, #thisRel do
|
||||||
|
thisRel[i] = 2 ^ thisRel[i]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function getBestColourMatch(usage)
|
||||||
|
local lastCol = relations[exponents[usage[#usage][1]]]
|
||||||
|
if(lastCol~=nil)then
|
||||||
|
for j = 1, #lastCol do
|
||||||
|
local thisRelation = lastCol[j]
|
||||||
|
for i = 1, #usage - 1 do
|
||||||
|
if usage[i][1] == thisRelation then
|
||||||
|
return i
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
|
||||||
|
local function colsToChar(pattern, totals)
|
||||||
|
if not totals then
|
||||||
|
local newPattern = {}
|
||||||
|
totals = {}
|
||||||
|
for i = 1, 6 do
|
||||||
|
local thisVal = pattern[i]
|
||||||
|
local thisTot = totals[thisVal]
|
||||||
|
totals[thisVal], newPattern[i] = thisTot and (thisTot + 1) or 1, thisVal
|
||||||
|
end
|
||||||
|
pattern = newPattern
|
||||||
|
end
|
||||||
|
|
||||||
|
local usage = {}
|
||||||
|
for key, value in pairs(totals) do
|
||||||
|
usage[#usage + 1] = { key, value }
|
||||||
|
end
|
||||||
|
|
||||||
|
if #usage > 1 then
|
||||||
|
-- Reduce the chunk to two colours:
|
||||||
|
while #usage > 2 do
|
||||||
|
table.sort(usage, function(a, b)
|
||||||
|
return a[2] > b[2]
|
||||||
|
end)
|
||||||
|
local matchToInd, usageLen = getBestColourMatch(usage), #usage
|
||||||
|
local matchFrom, matchTo = usage[usageLen][1], usage[matchToInd][1]
|
||||||
|
for i = 1, 6 do
|
||||||
|
if pattern[i] == matchFrom then
|
||||||
|
pattern[i] = matchTo
|
||||||
|
usage[matchToInd][2] = usage[matchToInd][2] + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
usage[usageLen] = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Convert to character. Adapted from oli414's function:
|
||||||
|
-- http://www.computercraft.info/forums2/index.php?/topic/25340-cc-176-easy-drawing-characters/
|
||||||
|
local data = 128
|
||||||
|
for i = 1, #pattern - 1 do
|
||||||
|
if pattern[i] ~= pattern[6] then
|
||||||
|
data = data + 2 ^ (i - 1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return string.char(data), colourChar[usage[1][1] == pattern[6] and usage[2][1] or usage[1][1]], colourChar[pattern[6]]
|
||||||
|
else
|
||||||
|
-- Solid colour character:
|
||||||
|
return "\128", colourChar[pattern[1]], colourChar[pattern[1]]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local results, width, height, bgCol = { {}, {}, {} }, 0, #bLittleData + #bLittleData % 3, bgColor or colors.black
|
||||||
|
for i = 1, #bLittleData do
|
||||||
|
if #bLittleData[i] > width then
|
||||||
|
width = #bLittleData[i]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for y = 0, height - 1, 3 do
|
||||||
|
local cRow, tRow, bRow, counter = {}, {}, {}, 1
|
||||||
|
|
||||||
|
for x = 0, width - 1, 2 do
|
||||||
|
-- Grab a 2x3 chunk:
|
||||||
|
local pattern, totals = {}, {}
|
||||||
|
|
||||||
|
for yy = 1, 3 do
|
||||||
|
for xx = 1, 2 do
|
||||||
|
pattern[#pattern + 1] = (bLittleData[y + yy] and bLittleData[y + yy][x + xx]) and (bLittleData[y + yy][x + xx] == 0 and bgCol or bLittleData[y + yy][x + xx]) or bgCol
|
||||||
|
totals[pattern[#pattern]] = totals[pattern[#pattern]] and (totals[pattern[#pattern]] + 1) or 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
cRow[counter], tRow[counter], bRow[counter] = colsToChar(pattern, totals)
|
||||||
|
counter = counter + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
results[1][#results[1] + 1], results[2][#results[2] + 1], results[3][#results[3] + 1] = table.concat(cRow), table.concat(tRow), table.concat(bRow)
|
||||||
|
end
|
||||||
|
|
||||||
|
results.width, results.height = #results[1][1], #results[1]
|
||||||
|
|
||||||
|
return results
|
||||||
|
end,
|
||||||
|
|
||||||
|
}
|
||||||
14
Basalt/loadObjects.lua
Normal file
14
Basalt/loadObjects.lua
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
local _OBJECTS = {}
|
||||||
|
if(packaged)then
|
||||||
|
for k,v in pairs(getProject("objects"))do
|
||||||
|
_OBJECTS[k] = v()
|
||||||
|
end
|
||||||
|
return _OBJECTS
|
||||||
|
end
|
||||||
|
for _,v in pairs(fs.list(fs.combine("Basalt", "objects")))do
|
||||||
|
if(v~="example.lua")then
|
||||||
|
local name = v:gsub(".lua", "")
|
||||||
|
_OBJECTS[name] = require(name)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return _OBJECTS
|
||||||
219
Basalt/main.lua
Normal file
219
Basalt/main.lua
Normal file
@@ -0,0 +1,219 @@
|
|||||||
|
local basaltEvent = require("basaltEvent")()
|
||||||
|
local Frame = require("Frame")
|
||||||
|
|
||||||
|
local baseTerm = term.current()
|
||||||
|
local version = 2
|
||||||
|
local debugger = true
|
||||||
|
|
||||||
|
local projectDirectory = fs.getDir(table.pack(...)[2] or "")
|
||||||
|
|
||||||
|
local activeKey, frames, monFrames = {}, {}, {}
|
||||||
|
local mainFrame, activeFrame, focusedObject, updaterActive
|
||||||
|
|
||||||
|
local function stop()
|
||||||
|
updaterActive = false
|
||||||
|
end
|
||||||
|
|
||||||
|
local bInstance = {
|
||||||
|
getMainFrame = function()
|
||||||
|
return mainFrame
|
||||||
|
end,
|
||||||
|
|
||||||
|
setMainFrame = function(mFrame)
|
||||||
|
mainFrame = mFrame
|
||||||
|
end,
|
||||||
|
|
||||||
|
getActiveFrame = function()
|
||||||
|
return activeFrame
|
||||||
|
end,
|
||||||
|
|
||||||
|
setActiveFrame = function(aFrame)
|
||||||
|
activeFrame = aFrame
|
||||||
|
end,
|
||||||
|
|
||||||
|
getFocusedObject = function()
|
||||||
|
return focusedObject
|
||||||
|
end,
|
||||||
|
|
||||||
|
setFocusedObject = function(focused)
|
||||||
|
focusedObject = focused
|
||||||
|
end,
|
||||||
|
|
||||||
|
getMonitorFrame = function(name)
|
||||||
|
return monFrames[name]
|
||||||
|
end,
|
||||||
|
|
||||||
|
setMonitorFrame = function(name, frame)
|
||||||
|
monFrames[name] = frame
|
||||||
|
end,
|
||||||
|
|
||||||
|
getBaseTerm = function()
|
||||||
|
return baseTerm
|
||||||
|
end,
|
||||||
|
|
||||||
|
stop = stop,
|
||||||
|
newFrame = Frame,
|
||||||
|
|
||||||
|
getDirectory = function()
|
||||||
|
return projectDirectory
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
|
local function drawFrames()
|
||||||
|
mainFrame:draw()
|
||||||
|
mainFrame:drawUpdate()
|
||||||
|
for _,v in pairs(monFrames)do
|
||||||
|
v:draw()
|
||||||
|
v:drawUpdate()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function basaltUpdateEvent(event, p1, p2, p3, p4)
|
||||||
|
if(basaltEvent:sendEvent("basaltEventCycle", event, p1, p2, p3, p4)==false)then return end
|
||||||
|
if(mainFrame~=nil)then
|
||||||
|
if (event == "mouse_click") then
|
||||||
|
mainFrame:mouseHandler(event, p1, p2, p3, p4)
|
||||||
|
activeFrame = mainFrame
|
||||||
|
elseif (event == "mouse_drag") then
|
||||||
|
mainFrame:mouseHandler(event, p1, p2, p3, p4)
|
||||||
|
activeFrame = mainFrame
|
||||||
|
elseif (event == "mouse_up") then
|
||||||
|
mainFrame:mouseHandler(event, p1, p2, p3, p4)
|
||||||
|
activeFrame = mainFrame
|
||||||
|
elseif (event == "mouse_scroll") then
|
||||||
|
mainFrame:mouseHandler(event, p1, p2, p3, p4)
|
||||||
|
activeFrame = mainFrame
|
||||||
|
elseif (event == "monitor_touch") then
|
||||||
|
if(monFrames[p1]~=nil)then
|
||||||
|
monFrames[p1]:mouseHandler(event, p1, p2, p3, p4)
|
||||||
|
activeFrame = monFrames[p1]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if(event == "key") or (event == "char") then
|
||||||
|
activeFrame:keyHandler(event, p1)
|
||||||
|
activeFrame:backgroundKeyHandler(event, p1)
|
||||||
|
end
|
||||||
|
|
||||||
|
if(event == "key")then
|
||||||
|
activeKey[p1] = true
|
||||||
|
end
|
||||||
|
|
||||||
|
if(event == "key_up")then
|
||||||
|
activeKey[p1] = false
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, v in pairs(frames) do
|
||||||
|
v:eventHandler(event, p1, p2, p3, p4)
|
||||||
|
end
|
||||||
|
drawFrames()
|
||||||
|
end
|
||||||
|
|
||||||
|
local basalt = {}
|
||||||
|
basalt = {
|
||||||
|
|
||||||
|
setBaseTerm = function(_baseTerm)
|
||||||
|
baseTerm = _baseTerm
|
||||||
|
end,
|
||||||
|
|
||||||
|
autoUpdate = function(isActive)
|
||||||
|
updaterActive = isActive
|
||||||
|
if(isActive==nil)then updaterActive = true end
|
||||||
|
drawFrames()
|
||||||
|
while updaterActive do
|
||||||
|
local event, p1, p2, p3, p4 = os.pullEventRaw()
|
||||||
|
basaltUpdateEvent(event, p1, p2, p3, p4)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
|
||||||
|
update = function(event, p1, p2, p3, p4)
|
||||||
|
if (event ~= nil) then
|
||||||
|
basaltUpdateEvent(event, p1, p2, p3, p4)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
|
||||||
|
stop = stop,
|
||||||
|
|
||||||
|
isKeyDown = function(key)
|
||||||
|
if(activeKey[key]==nil)then return false end
|
||||||
|
return activeKey[key];
|
||||||
|
end,
|
||||||
|
|
||||||
|
getFrame = function(name)
|
||||||
|
for _, value in pairs(frames) do
|
||||||
|
if (value.name == name) then
|
||||||
|
return value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
|
||||||
|
getActiveFrame = function()
|
||||||
|
return activeFrame
|
||||||
|
end,
|
||||||
|
|
||||||
|
setActiveFrame = function(frame)
|
||||||
|
if (frame:getType() == "Frame") then
|
||||||
|
activeFrame = frame
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end,
|
||||||
|
|
||||||
|
onEvent = function(...)
|
||||||
|
for _,v in pairs(table.pack(...))do
|
||||||
|
if(type(v)=="function")then
|
||||||
|
basaltEvent:registerEvent("basaltEventCycle", v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
|
||||||
|
createFrame = function(name)
|
||||||
|
for _, v in pairs(frames) do
|
||||||
|
if (v.name == name) then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local newFrame = Frame(name,nil,nil,bInstance)
|
||||||
|
table.insert(frames, newFrame)
|
||||||
|
return newFrame
|
||||||
|
end,
|
||||||
|
|
||||||
|
removeFrame = function(name)
|
||||||
|
frames[name] = nil
|
||||||
|
end,
|
||||||
|
|
||||||
|
setProjectDir = function(dir)
|
||||||
|
projectDirectory = dir
|
||||||
|
end,
|
||||||
|
|
||||||
|
debug = function(...)
|
||||||
|
local args = { ... }
|
||||||
|
if (mainFrame.name ~= "basaltDebuggingFrame") then
|
||||||
|
if (mainFrame ~= basalt.debugFrame) then
|
||||||
|
basalt.debugLabel:setParent(mainFrame)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local str = ""
|
||||||
|
for key, value in pairs(args) do
|
||||||
|
str = str .. tostring(value) .. (#args ~= key and ", " or "")
|
||||||
|
end
|
||||||
|
basalt.debugLabel:setText("[Debug] " .. str)
|
||||||
|
basalt.debugList:addItem(str)
|
||||||
|
if (basalt.debugList:getItemCount() > 50) then
|
||||||
|
basalt.debugList:removeItem(1)
|
||||||
|
end
|
||||||
|
basalt.debugList:setValue(basalt.debugList:getItem(basalt.debugList:getItemCount()))
|
||||||
|
if(basalt.debugList.getItemCount() > basalt.debugList:getHeight())then
|
||||||
|
basalt.debugList:setIndexOffset(basalt.debugList:getItemCount() - basalt.debugList:getHeight())
|
||||||
|
end
|
||||||
|
basalt.debugLabel:show()
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
|
||||||
|
basalt.debugFrame = basalt.createFrame("basaltDebuggingFrame"):showBar():setBackground(colors.lightGray):setBar("Debug", colors.black, colors.gray)
|
||||||
|
basalt.debugFrame:addButton("back"):setAnchor("topRight"):setSize(1, 1):setText("\22"):onClick(function() basalt.oldFrame:show() end):setBackground(colors.red):show()
|
||||||
|
basalt.debugList = basalt.debugFrame:addList("debugList"):setSize(basalt.debugFrame.width - 2, basalt.debugFrame.height - 3):setPosition(2, 3):setScrollable(true):show()
|
||||||
|
basalt.debugLabel = basalt.debugFrame:addLabel("debugLabel"):onClick(function() basalt.oldFrame = mainFrame basalt.debugFrame:show() end):setBackground(colors.black):setForeground(colors.white):setAnchor("bottomLeft"):ignoreOffset():setZIndex(20):show()
|
||||||
|
|
||||||
|
return basalt
|
||||||
95
Basalt/objects/Animation.lua
Normal file
95
Basalt/objects/Animation.lua
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
return function(name)
|
||||||
|
local object = {}
|
||||||
|
local objectType = "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 objectType
|
||||||
|
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
|
||||||
59
Basalt/objects/Button.lua
Normal file
59
Basalt/objects/Button.lua
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
local Object = require("Object")
|
||||||
|
local theme = require("theme")
|
||||||
|
local utils = require("utils")
|
||||||
|
|
||||||
|
return function(name)
|
||||||
|
-- Button
|
||||||
|
local base = Object(name)
|
||||||
|
local objectType = "Button"
|
||||||
|
|
||||||
|
base:setValue("Button")
|
||||||
|
base:setZIndex(5)
|
||||||
|
base.width = 8
|
||||||
|
base.bgColor = theme.ButtonBG
|
||||||
|
base.fgColor = theme.ButtonFG
|
||||||
|
|
||||||
|
local textHorizontalAlign = "center"
|
||||||
|
local textVerticalAlign = "center"
|
||||||
|
|
||||||
|
local object = {
|
||||||
|
getType = function(self)
|
||||||
|
return objectType
|
||||||
|
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()
|
||||||
|
local verticalAlign = utils.getTextVerticalAlign(self.height, textVerticalAlign)
|
||||||
|
|
||||||
|
if(self.bgColor~=false)then
|
||||||
|
self.parent:drawBackgroundBox(obx, oby, self.width, self.height, self.bgColor)
|
||||||
|
self.parent:drawTextBox(obx, oby, self.width, self.height, " ")
|
||||||
|
end
|
||||||
|
if(self.fgColor~=false)then self.parent:drawForegroundBox(obx, oby, self.width, self.height, self.fgColor) end
|
||||||
|
for n = 1, self.height do
|
||||||
|
if (n == verticalAlign) then
|
||||||
|
self.parent:setText(obx, oby + (n - 1), utils.getTextHorizontalAlign(self:getValue(), self.width, textHorizontalAlign))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
self:setVisualChanged(false)
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
|
||||||
|
}
|
||||||
|
return setmetatable(object, base)
|
||||||
|
end
|
||||||
62
Basalt/objects/Checkbox.lua
Normal file
62
Basalt/objects/Checkbox.lua
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
local Object = require("Object")
|
||||||
|
local theme = require("theme")
|
||||||
|
local utils = require("utils")
|
||||||
|
|
||||||
|
return function(name)
|
||||||
|
-- Checkbox
|
||||||
|
local base = Object(name)
|
||||||
|
local objectType = "Checkbox"
|
||||||
|
|
||||||
|
base:setZIndex(5)
|
||||||
|
base:setValue(false)
|
||||||
|
base.width = 1
|
||||||
|
base.height = 1
|
||||||
|
base.bgColor = theme.CheckboxBG
|
||||||
|
base.fgColor = theme.CheckboxFG
|
||||||
|
|
||||||
|
local object = {
|
||||||
|
symbol = "\42",
|
||||||
|
|
||||||
|
getType = function(self)
|
||||||
|
return objectType
|
||||||
|
end;
|
||||||
|
|
||||||
|
mouseHandler = function(self, event, button, x, y)
|
||||||
|
if (base.mouseHandler(self, event, button, x, y)) then
|
||||||
|
if ((event == "mouse_click") and (button == 1)) or (event == "monitor_touch") 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 = utils.getTextVerticalAlign(self.height, "center")
|
||||||
|
|
||||||
|
if(self.bgColor~=false)then self.parent:drawBackgroundBox(obx, oby, self.width, self.height, self.bgColor) end
|
||||||
|
for n = 1, self.height do
|
||||||
|
if (n == verticalAlign) then
|
||||||
|
if (self:getValue() == true) then
|
||||||
|
self.parent:writeText(obx, oby + (n - 1), utils.getTextHorizontalAlign(self.symbol, self.width, "center"), self.bgColor, self.fgColor)
|
||||||
|
else
|
||||||
|
self.parent:writeText(obx, oby + (n - 1), utils.getTextHorizontalAlign(" ", self.width, "center"), self.bgColor, self.fgColor)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
self:setVisualChanged(false)
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return setmetatable(object, base)
|
||||||
|
end
|
||||||
174
Basalt/objects/Dropdown.lua
Normal file
174
Basalt/objects/Dropdown.lua
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
local Object = require("Object")
|
||||||
|
local theme = require("theme")
|
||||||
|
local utils = require("utils")
|
||||||
|
|
||||||
|
return function(name)
|
||||||
|
local base = Object(name)
|
||||||
|
local objectType = "Dropdown"
|
||||||
|
base.width = 12
|
||||||
|
base.height = 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 isOpened = false
|
||||||
|
|
||||||
|
local object = {
|
||||||
|
getType = function(self)
|
||||||
|
return objectType
|
||||||
|
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 = { ... } })
|
||||||
|
return self
|
||||||
|
end;
|
||||||
|
|
||||||
|
getAll = function(self)
|
||||||
|
return list
|
||||||
|
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 key, value in pairs(list) do
|
||||||
|
if (value == selected) then
|
||||||
|
return key
|
||||||
|
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, width, height)
|
||||||
|
dropdownW, dropdownH = width, height
|
||||||
|
return self
|
||||||
|
end;
|
||||||
|
|
||||||
|
mouseHandler = function(self, event, button, x, y)
|
||||||
|
if (isOpened) then
|
||||||
|
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition())
|
||||||
|
if ((event == "mouse_click") and (button == 1)) or (event == "monitor_touch") 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
|
||||||
|
|
||||||
|
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
|
||||||
|
isOpened = true
|
||||||
|
else
|
||||||
|
isOpened = false
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
|
||||||
|
draw = function(self)
|
||||||
|
if (base.draw(self)) then
|
||||||
|
local obx, oby = self:getAnchorPosition()
|
||||||
|
if (self.parent ~= nil) then
|
||||||
|
if(self.bgColor~=false)then self.parent:drawBackgroundBox(obx, oby, self.width, self.height, self.bgColor) end
|
||||||
|
local val = self:getValue()
|
||||||
|
local text = utils.getTextHorizontalAlign((val~=nil and val.text or ""), self.width, align):sub(1, self.width - 1) .. (isOpened and openedSymbol or closedSymbol)
|
||||||
|
self.parent:writeText(obx, oby, text, self.bgColor, self.fgColor)
|
||||||
|
|
||||||
|
if (isOpened) then
|
||||||
|
for n = 1, dropdownH do
|
||||||
|
if (list[n + yOffset] ~= nil) then
|
||||||
|
if (list[n + yOffset] == val) then
|
||||||
|
if (selectionColorActive) then
|
||||||
|
self.parent:writeText(obx, oby + n, utils.getTextHorizontalAlign(list[n + yOffset].text, dropdownW, align), itemSelectedBG, itemSelectedFG)
|
||||||
|
else
|
||||||
|
self.parent:writeText(obx, oby + n, utils.getTextHorizontalAlign(list[n + yOffset].text, dropdownW, align), list[n + yOffset].bgCol, list[n + yOffset].fgCol)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
self.parent:writeText(obx, oby + n, utils.getTextHorizontalAlign(list[n + yOffset].text, dropdownW, align), list[n + yOffset].bgCol, list[n + yOffset].fgCol)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
self:setVisualChanged(false)
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
}
|
||||||
|
|
||||||
|
return setmetatable(object, base)
|
||||||
|
end
|
||||||
188
Basalt/objects/Image.lua
Normal file
188
Basalt/objects/Image.lua
Normal file
@@ -0,0 +1,188 @@
|
|||||||
|
return function(name)
|
||||||
|
-- Pane
|
||||||
|
local base = Object(name)
|
||||||
|
local objectType = "Image"
|
||||||
|
base:setZIndex(2)
|
||||||
|
local image
|
||||||
|
local shrinkedImage
|
||||||
|
local imageGotShrinked = false
|
||||||
|
|
||||||
|
local function shrink()
|
||||||
|
|
||||||
|
-- shrinkSystem is copy pasted (and slightly changed) from blittle by Bomb Bloke: http://www.computercraft.info/forums2/index.php?/topic/25354-cc-176-blittle-api/
|
||||||
|
local relations = { [0] = { 8, 4, 3, 6, 5 }, { 4, 14, 8, 7 }, { 6, 10, 8, 7 }, { 9, 11, 8, 0 }, { 1, 14, 8, 0 }, { 13, 12, 8, 0 }, { 2, 10, 8, 0 }, { 15, 8, 10, 11, 12, 14 },
|
||||||
|
{ 0, 7, 1, 9, 2, 13 }, { 3, 11, 8, 7 }, { 2, 6, 7, 15 }, { 9, 3, 7, 15 }, { 13, 5, 7, 15 }, { 5, 12, 8, 7 }, { 1, 4, 7, 15 }, { 7, 10, 11, 12, 14 } }
|
||||||
|
|
||||||
|
local colourNum, exponents, colourChar = {}, {}, {}
|
||||||
|
for i = 0, 15 do
|
||||||
|
exponents[2 ^ i] = i
|
||||||
|
end
|
||||||
|
do
|
||||||
|
local hex = "0123456789abcdef"
|
||||||
|
for i = 1, 16 do
|
||||||
|
colourNum[hex:sub(i, i)] = i - 1
|
||||||
|
colourNum[i - 1] = hex:sub(i, i)
|
||||||
|
colourChar[hex:sub(i, i)] = 2 ^ (i - 1)
|
||||||
|
colourChar[2 ^ (i - 1)] = hex:sub(i, i)
|
||||||
|
|
||||||
|
local thisRel = relations[i - 1]
|
||||||
|
for i = 1, #thisRel do
|
||||||
|
thisRel[i] = 2 ^ thisRel[i]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function getBestColourMatch(usage)
|
||||||
|
local lastCol = relations[exponents[usage[#usage][1]]]
|
||||||
|
|
||||||
|
for j = 1, #lastCol do
|
||||||
|
local thisRelation = lastCol[j]
|
||||||
|
for i = 1, #usage - 1 do
|
||||||
|
if usage[i][1] == thisRelation then
|
||||||
|
return i
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
|
||||||
|
local function colsToChar(pattern, totals)
|
||||||
|
if not totals then
|
||||||
|
local newPattern = {}
|
||||||
|
totals = {}
|
||||||
|
for i = 1, 6 do
|
||||||
|
local thisVal = pattern[i]
|
||||||
|
local thisTot = totals[thisVal]
|
||||||
|
totals[thisVal], newPattern[i] = thisTot and (thisTot + 1) or 1, thisVal
|
||||||
|
end
|
||||||
|
pattern = newPattern
|
||||||
|
end
|
||||||
|
|
||||||
|
local usage = {}
|
||||||
|
for key, value in pairs(totals) do
|
||||||
|
usage[#usage + 1] = { key, value }
|
||||||
|
end
|
||||||
|
|
||||||
|
if #usage > 1 then
|
||||||
|
-- Reduce the chunk to two colours:
|
||||||
|
while #usage > 2 do
|
||||||
|
table.sort(usage, function(a, b)
|
||||||
|
return a[2] > b[2]
|
||||||
|
end)
|
||||||
|
local matchToInd, usageLen = getBestColourMatch(usage), #usage
|
||||||
|
local matchFrom, matchTo = usage[usageLen][1], usage[matchToInd][1]
|
||||||
|
for i = 1, 6 do
|
||||||
|
if pattern[i] == matchFrom then
|
||||||
|
pattern[i] = matchTo
|
||||||
|
usage[matchToInd][2] = usage[matchToInd][2] + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
usage[usageLen] = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Convert to character. Adapted from oli414's function:
|
||||||
|
-- http://www.computercraft.info/forums2/index.php?/topic/25340-cc-176-easy-drawing-characters/
|
||||||
|
local data = 128
|
||||||
|
for i = 1, #pattern - 1 do
|
||||||
|
if pattern[i] ~= pattern[6] then
|
||||||
|
data = data + 2 ^ (i - 1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return string.char(data), colourChar[usage[1][1] == pattern[6] and usage[2][1] or usage[1][1]], colourChar[pattern[6]]
|
||||||
|
else
|
||||||
|
-- Solid colour character:
|
||||||
|
return "\128", colourChar[pattern[1]], colourChar[pattern[1]]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local results, width, height, bgCol = { {}, {}, {} }, 0, #image + #image % 3, base.bgColor or colors.black
|
||||||
|
for i = 1, #image do
|
||||||
|
if #image[i] > width then
|
||||||
|
width = #image[i]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for y = 0, height - 1, 3 do
|
||||||
|
local cRow, tRow, bRow, counter = {}, {}, {}, 1
|
||||||
|
|
||||||
|
for x = 0, width - 1, 2 do
|
||||||
|
-- Grab a 2x3 chunk:
|
||||||
|
local pattern, totals = {}, {}
|
||||||
|
|
||||||
|
for yy = 1, 3 do
|
||||||
|
for xx = 1, 2 do
|
||||||
|
pattern[#pattern + 1] = (image[y + yy] and image[y + yy][x + xx]) and (image[y + yy][x + xx] == 0 and bgCol or image[y + yy][x + xx]) or bgCol
|
||||||
|
totals[pattern[#pattern]] = totals[pattern[#pattern]] and (totals[pattern[#pattern]] + 1) or 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
cRow[counter], tRow[counter], bRow[counter] = colsToChar(pattern, totals)
|
||||||
|
counter = counter + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
results[1][#results[1] + 1], results[2][#results[2] + 1], results[3][#results[3] + 1] = table.concat(cRow), table.concat(tRow), table.concat(bRow)
|
||||||
|
end
|
||||||
|
|
||||||
|
results.width, results.height = #results[1][1], #results[1]
|
||||||
|
|
||||||
|
shrinkedImage = results
|
||||||
|
end
|
||||||
|
|
||||||
|
local object = {
|
||||||
|
getType = function(self)
|
||||||
|
return objectType
|
||||||
|
end;
|
||||||
|
|
||||||
|
loadImage = function(self, path)
|
||||||
|
image = paintutils.loadImage(path)
|
||||||
|
imageGotShrinked = false
|
||||||
|
return self
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
shrink = function(self)
|
||||||
|
shrink()
|
||||||
|
imageGotShrinked = true
|
||||||
|
return self
|
||||||
|
end;
|
||||||
|
|
||||||
|
draw = function(self)
|
||||||
|
if (base.draw(self)) then
|
||||||
|
if (self.parent ~= nil) then
|
||||||
|
if (image ~= nil) then
|
||||||
|
local obx, oby = self:getAnchorPosition()
|
||||||
|
if (imageGotShrinked) then
|
||||||
|
-- this is copy pasted (and slightly changed) from blittle by Bomb Bloke: http://www.computercraft.info/forums2/index.php?/topic/25354-cc-176-blittle-api/
|
||||||
|
local t, tC, bC = shrinkedImage[1], shrinkedImage[2], shrinkedImage[3]
|
||||||
|
for i = 1, shrinkedImage.height do
|
||||||
|
local tI = t[i]
|
||||||
|
if type(tI) == "string" then
|
||||||
|
self.parent:setText(obx, oby + i - 1, tI)
|
||||||
|
self.parent:setFG(obx, oby + i - 1, tC[i])
|
||||||
|
self.parent:setBG(obx, oby + i - 1, bC[i])
|
||||||
|
elseif type(tI) == "table" then
|
||||||
|
self.parent:setText(obx, oby + i - 1, tI[2])
|
||||||
|
self.parent:setFG(obx, oby + i - 1, tC[i])
|
||||||
|
self.parent:setBG(obx, oby + i - 1, bC[i])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
for yPos = 1, math.min(#image, self.height) do
|
||||||
|
local line = image[yPos]
|
||||||
|
for xPos = 1, math.min(#line, self.width) do
|
||||||
|
if line[xPos] > 0 then
|
||||||
|
self.parent:drawBackgroundBox(obx + xPos - 1, oby + yPos - 1, 1, 1, line[xPos])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
self:setVisualChanged(false)
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
}
|
||||||
|
|
||||||
|
return setmetatable(object, base)
|
||||||
|
end
|
||||||
246
Basalt/objects/Input.lua
Normal file
246
Basalt/objects/Input.lua
Normal file
@@ -0,0 +1,246 @@
|
|||||||
|
local Object = require("Object")
|
||||||
|
local theme = require("theme")
|
||||||
|
local utils = require("utils")
|
||||||
|
|
||||||
|
return function(name)
|
||||||
|
-- Input
|
||||||
|
local base = Object(name)
|
||||||
|
local objectType = "Input"
|
||||||
|
|
||||||
|
local inputType = "text"
|
||||||
|
local inputLimit = 0
|
||||||
|
base:setZIndex(5)
|
||||||
|
base:setValue("")
|
||||||
|
base.width = 10
|
||||||
|
base.height = 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 objectType
|
||||||
|
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+math.floor(self.height/2), 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 == keys.backspace) then
|
||||||
|
-- on backspace
|
||||||
|
local text = tostring(base.getValue())
|
||||||
|
if (textX > 1) then
|
||||||
|
self:setValue(text:sub(1, textX - 2) .. text:sub(textX, text:len()))
|
||||||
|
if (textX > 1) then
|
||||||
|
textX = textX - 1
|
||||||
|
end
|
||||||
|
if (wIndex > 1) then
|
||||||
|
if (textX < wIndex) then
|
||||||
|
wIndex = wIndex - 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if (key == keys.enter) then
|
||||||
|
-- on enter
|
||||||
|
if (self.parent ~= nil) then
|
||||||
|
--self.parent:removeFocusedObject(self)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if (key == keys.right) then
|
||||||
|
-- right arrow
|
||||||
|
local tLength = tostring(base.getValue()):len()
|
||||||
|
textX = textX + 1
|
||||||
|
|
||||||
|
if (textX > tLength) then
|
||||||
|
textX = tLength + 1
|
||||||
|
end
|
||||||
|
if (textX < 1) then
|
||||||
|
textX = 1
|
||||||
|
end
|
||||||
|
if (textX < wIndex) or (textX >= self.width + wIndex) then
|
||||||
|
wIndex = textX - self.width + 1
|
||||||
|
end
|
||||||
|
if (wIndex < 1) then
|
||||||
|
wIndex = 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if (key == keys.left) then
|
||||||
|
-- left arrow
|
||||||
|
textX = textX - 1
|
||||||
|
if (textX >= 1) then
|
||||||
|
if (textX < wIndex) or (textX >= self.width + 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.width + 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.width - 1) then
|
||||||
|
cursorX = self.x + self.width - 1
|
||||||
|
end
|
||||||
|
if (self.parent ~= nil) then
|
||||||
|
self.parent:setCursor(true, obx + cursorX, oby+math.floor(self.height/2), 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 = utils.getTextVerticalAlign(self.height, "center")
|
||||||
|
|
||||||
|
if(self.bgColor~=false)then self.parent:drawBackgroundBox(obx, oby, self.width, self.height, self.bgColor) end
|
||||||
|
for n = 1, self.height do
|
||||||
|
if (n == verticalAlign) then
|
||||||
|
local val = tostring(base.getValue())
|
||||||
|
local bCol = self.bgColor
|
||||||
|
local fCol = self.fgColor
|
||||||
|
local text
|
||||||
|
if (val:len() <= 0) then
|
||||||
|
text = showingText
|
||||||
|
bCol = defaultBGCol or bCol
|
||||||
|
fCol = defaultFGCol or fCol
|
||||||
|
end
|
||||||
|
|
||||||
|
text = showingText
|
||||||
|
if (val ~= "") then
|
||||||
|
text = val
|
||||||
|
end
|
||||||
|
text = text:sub(wIndex, self.width + wIndex - 1)
|
||||||
|
local space = self.width - text:len()
|
||||||
|
if (space < 0) then
|
||||||
|
space = 0
|
||||||
|
end
|
||||||
|
if (inputType == "password") and (val ~= "") then
|
||||||
|
text = string.rep("*", text:len())
|
||||||
|
end
|
||||||
|
text = text .. string.rep(" ", space)
|
||||||
|
self.parent:writeText(obx, oby + (n - 1), text, bCol, fCol)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
self:setVisualChanged(false)
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
}
|
||||||
|
|
||||||
|
return setmetatable(object, base)
|
||||||
|
end
|
||||||
119
Basalt/objects/Label.lua
Normal file
119
Basalt/objects/Label.lua
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
local Object = require("Object")
|
||||||
|
local theme = require("theme")
|
||||||
|
local utils = require("utils")
|
||||||
|
local tHex = require("tHex")
|
||||||
|
local bigFont = require("bigfont")
|
||||||
|
|
||||||
|
return function(name)
|
||||||
|
-- Label
|
||||||
|
local base = Object(name)
|
||||||
|
local objectType = "Label"
|
||||||
|
|
||||||
|
base:setZIndex(3)
|
||||||
|
|
||||||
|
local autoSize = true
|
||||||
|
base:setValue("")
|
||||||
|
|
||||||
|
local textHorizontalAlign = "left"
|
||||||
|
local textVerticalAlign = "top"
|
||||||
|
local fontsize = 0
|
||||||
|
|
||||||
|
local fgColChanged,bgColChanged = false,false
|
||||||
|
|
||||||
|
local object = {
|
||||||
|
getType = function(self)
|
||||||
|
return objectType
|
||||||
|
end;
|
||||||
|
setText = function(self, text)
|
||||||
|
text = tostring(text)
|
||||||
|
base:setValue(text)
|
||||||
|
if (autoSize) then
|
||||||
|
self.width = text:len()
|
||||||
|
end
|
||||||
|
if not(fgColChanged)then self.fgColor = self.parent:getForeground() or colors.white end
|
||||||
|
if not(bgColChanged)then self.bgColor = self.parent:getBackground() or colors.black end
|
||||||
|
return self
|
||||||
|
end;
|
||||||
|
|
||||||
|
setBackground = function(self, col)
|
||||||
|
base.setBackground(self, col)
|
||||||
|
bgColChanged = true
|
||||||
|
return self
|
||||||
|
end,
|
||||||
|
|
||||||
|
setForeground = function(self, col)
|
||||||
|
base.setForeground(self, col)
|
||||||
|
fgColChanged = true
|
||||||
|
return self
|
||||||
|
end,
|
||||||
|
|
||||||
|
setTextAlign = function(self, hor, vert)
|
||||||
|
textHorizontalAlign = hor or textHorizontalAlign
|
||||||
|
textVerticalAlign = vert or textVerticalAlign
|
||||||
|
self:setVisualChanged()
|
||||||
|
return self
|
||||||
|
end;
|
||||||
|
|
||||||
|
setFontSize = function(self, size)
|
||||||
|
if(size>0)and(size<=4)then
|
||||||
|
fontsize = size-1 or 0
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end;
|
||||||
|
|
||||||
|
getFontSize = function(self)
|
||||||
|
return fontsize+1
|
||||||
|
end;
|
||||||
|
|
||||||
|
setSize = function(self, width, height)
|
||||||
|
base.setSize(self, width, height)
|
||||||
|
autoSize = false
|
||||||
|
self:setVisualChanged()
|
||||||
|
return self
|
||||||
|
end;
|
||||||
|
|
||||||
|
draw = function(self)
|
||||||
|
if (base.draw(self)) then
|
||||||
|
if (self.parent ~= nil) then
|
||||||
|
local obx, oby = self:getAnchorPosition()
|
||||||
|
local verticalAlign = utils.getTextVerticalAlign(self.height, textVerticalAlign)
|
||||||
|
if(self.bgColor~=false)then
|
||||||
|
self.parent:drawBackgroundBox(obx, oby, self.width, self.height, self.bgColor)
|
||||||
|
self.parent:drawTextBox(obx, oby, self.width, self.height, " ") end
|
||||||
|
if(self.fgColor~=false)then self.parent:drawForegroundBox(obx, oby, self.width, self.height, self.fgColor) end
|
||||||
|
if(fontsize==0)then
|
||||||
|
for n = 1, self.height do
|
||||||
|
if (n == verticalAlign) then
|
||||||
|
self.parent:setText(obx, oby + (n - 1), utils.getTextHorizontalAlign(self:getValue(), self.width, textHorizontalAlign))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
local tData = bigFont(fontsize, self:getValue(), self.fgColor, self.bgColor or colors.black)
|
||||||
|
if(autoSize)then
|
||||||
|
self.height = #tData[1]-1
|
||||||
|
self.width = #tData[1][1]
|
||||||
|
end
|
||||||
|
for n = 1, self.height do
|
||||||
|
if (n == verticalAlign) then
|
||||||
|
local oX, oY = self.parent:getSize()
|
||||||
|
local cX, cY = #tData[1][1], #tData[1]
|
||||||
|
obx = obx or math.floor((oX - cX) / 2) + 1
|
||||||
|
oby = oby or math.floor((oY - cY) / 2) + 1
|
||||||
|
|
||||||
|
for i = 1, cY do
|
||||||
|
self.parent:setFG(obx, oby + i + n - 2, utils.getTextHorizontalAlign(tData[2][i], self.width, textHorizontalAlign))
|
||||||
|
self.parent:setBG(obx, oby + i + n - 2, utils.getTextHorizontalAlign(tData[3][i], self.width, textHorizontalAlign, tHex[self.bgColor or colors.black]))
|
||||||
|
self.parent:setText(obx, oby + i + n - 2, utils.getTextHorizontalAlign(tData[1][i], self.width, textHorizontalAlign))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
self:setVisualChanged(false)
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return setmetatable(object, base)
|
||||||
|
end
|
||||||
165
Basalt/objects/List.lua
Normal file
165
Basalt/objects/List.lua
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
local Object = require("Object")
|
||||||
|
local theme = require("theme")
|
||||||
|
local utils = require("utils")
|
||||||
|
|
||||||
|
return function(name)
|
||||||
|
local base = Object(name)
|
||||||
|
local objectType = "List"
|
||||||
|
base.width = 16
|
||||||
|
base.height = 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 objectType
|
||||||
|
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;
|
||||||
|
|
||||||
|
getAll = function(self)
|
||||||
|
return list
|
||||||
|
end;
|
||||||
|
|
||||||
|
getItemIndex = function(self)
|
||||||
|
local selected = self:getValue()
|
||||||
|
for key, value in pairs(list) do
|
||||||
|
if (value == selected) then
|
||||||
|
return key
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
|
||||||
|
clear = function(self)
|
||||||
|
list = {}
|
||||||
|
self:setValue({})
|
||||||
|
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)
|
||||||
|
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition())
|
||||||
|
if (obx <= x) and (obx + self.width > x) and (oby <= y) and (oby + self.height > y) and (self:isVisible()) then
|
||||||
|
if (((event == "mouse_click") or (event == "mouse_drag"))and(button==1))or(event=="monitor_touch") then
|
||||||
|
if (#list > 0) then
|
||||||
|
for n = 1, self.height do
|
||||||
|
if (list[n + yOffset] ~= nil) then
|
||||||
|
if (obx <= x) and (obx + self.width > x) and (oby + n - 1 == y) then
|
||||||
|
self:setValue(list[n + yOffset])
|
||||||
|
self:getEventSystem():sendEvent("mouse_click", self, "mouse_click", 0, x, y, list[n + yOffset])
|
||||||
|
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.height) then
|
||||||
|
if (yOffset > #list - self.height) then
|
||||||
|
yOffset = #list - self.height
|
||||||
|
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()
|
||||||
|
if(self.bgColor~=false)then
|
||||||
|
self.parent:drawBackgroundBox(obx, oby, self.width, self.height, self.bgColor)
|
||||||
|
end
|
||||||
|
for n = 1, self.height do
|
||||||
|
if (list[n + yOffset] ~= nil) then
|
||||||
|
if (list[n + yOffset] == self:getValue()) then
|
||||||
|
if (selectionColorActive) then
|
||||||
|
self.parent:writeText(obx, oby + n - 1, utils.getTextHorizontalAlign(list[n + yOffset].text, self.width, align), itemSelectedBG, itemSelectedFG)
|
||||||
|
else
|
||||||
|
self.parent:writeText(obx, oby + n - 1, utils.getTextHorizontalAlign(list[n + yOffset].text, self.width, align), list[n + yOffset].bgCol, list[n + yOffset].fgCol)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
self.parent:writeText(obx, oby + n - 1, utils.getTextHorizontalAlign(list[n + yOffset].text, self.width, align), list[n + yOffset].bgCol, list[n + yOffset].fgCol)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
self:setVisualChanged(false)
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
}
|
||||||
|
|
||||||
|
return setmetatable(object, base)
|
||||||
|
end
|
||||||
205
Basalt/objects/Menubar.lua
Normal file
205
Basalt/objects/Menubar.lua
Normal file
@@ -0,0 +1,205 @@
|
|||||||
|
local Object = require("Object")
|
||||||
|
local theme = require("theme")
|
||||||
|
local utils = require("utils")
|
||||||
|
local tHex = require("tHex")
|
||||||
|
|
||||||
|
return function(name)
|
||||||
|
local base = Object(name)
|
||||||
|
local objectType = "Menubar"
|
||||||
|
local object = {}
|
||||||
|
|
||||||
|
base.width = 30
|
||||||
|
base.height = 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 = 1
|
||||||
|
local scrollable = false
|
||||||
|
|
||||||
|
local function maxScroll()
|
||||||
|
local mScroll = 0
|
||||||
|
local xPos = 0
|
||||||
|
for n = 1, #list do
|
||||||
|
if (xPos + list[n].text:len() + space * 2 > object.width) then
|
||||||
|
if(xPos < object.width)then
|
||||||
|
mScroll = mScroll + (list[n].text:len() + space * 2-(object.width - xPos))
|
||||||
|
else
|
||||||
|
mScroll = mScroll + list[n].text:len() + space * 2
|
||||||
|
end
|
||||||
|
end
|
||||||
|
xPos = xPos + list[n].text:len() + space * 2
|
||||||
|
|
||||||
|
end
|
||||||
|
return mScroll
|
||||||
|
end
|
||||||
|
|
||||||
|
object = {
|
||||||
|
getType = function(self)
|
||||||
|
return objectType
|
||||||
|
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;
|
||||||
|
|
||||||
|
getAll = function(self)
|
||||||
|
return list
|
||||||
|
end;
|
||||||
|
|
||||||
|
getItemIndex = function(self)
|
||||||
|
local selected = self:getValue()
|
||||||
|
for key, value in pairs(list) do
|
||||||
|
if (value == selected) then
|
||||||
|
return key
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
|
||||||
|
clear = function(self)
|
||||||
|
list = {}
|
||||||
|
self:setValue({})
|
||||||
|
return self
|
||||||
|
end;
|
||||||
|
|
||||||
|
setSpace = function(self, _space)
|
||||||
|
space = _space or space
|
||||||
|
return self
|
||||||
|
end;
|
||||||
|
|
||||||
|
setPositionOffset = 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;
|
||||||
|
|
||||||
|
getPositionOffset = function(self)
|
||||||
|
return itemOffset
|
||||||
|
end;
|
||||||
|
|
||||||
|
setScrollable = function(self, scroll)
|
||||||
|
scrollable = scroll
|
||||||
|
if(scroll==nil)then scrollable = true end
|
||||||
|
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 objX, objY = self:getAbsolutePosition(self:getAnchorPosition())
|
||||||
|
if (objX <= x) and (objX + self.width > x) and (objY <= y) and (objY + self.height > y) and (self:isVisible()) then
|
||||||
|
if (self.parent ~= nil) then
|
||||||
|
self.parent:setFocusedObject(self)
|
||||||
|
end
|
||||||
|
if (event == "mouse_click") or (event == "monitor_touch") then
|
||||||
|
local xPos = 0
|
||||||
|
for n = 1, #list do
|
||||||
|
if (list[n] ~= nil) then
|
||||||
|
if (objX + xPos <= x + itemOffset) and (objX + xPos + list[n].text:len() + (space*2) > x + itemOffset) and (objY == y) then
|
||||||
|
self:setValue(list[n])
|
||||||
|
self:getEventSystem():sendEvent(event, self, event, 0, x, y, list[n])
|
||||||
|
end
|
||||||
|
xPos = xPos + list[n].text:len() + space * 2
|
||||||
|
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
|
||||||
|
self:setVisualChanged(true)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end;
|
||||||
|
|
||||||
|
draw = function(self)
|
||||||
|
if (base.draw(self)) then
|
||||||
|
if (self.parent ~= nil) then
|
||||||
|
local obx, oby = self:getAnchorPosition()
|
||||||
|
if(self.bgColor~=false)then
|
||||||
|
self.parent:drawBackgroundBox(obx, oby, self.width, self.height, self.bgColor)
|
||||||
|
end
|
||||||
|
local text = ""
|
||||||
|
local textBGCol = ""
|
||||||
|
local textFGCol = ""
|
||||||
|
for _, v in pairs(list) do
|
||||||
|
local newItem = (" "):rep(space) .. v.text .. (" "):rep(space)
|
||||||
|
text = text .. newItem
|
||||||
|
if(v == self:getValue())then
|
||||||
|
textBGCol = textBGCol .. tHex[itemSelectedBG or v.bgCol or self.bgColor]:rep(newItem:len())
|
||||||
|
textFGCol = textFGCol .. tHex[itemSelectedFG or v.FgCol or self.fgColor]:rep(newItem:len())
|
||||||
|
else
|
||||||
|
textBGCol = textBGCol .. tHex[v.bgCol or self.bgColor]:rep(newItem:len())
|
||||||
|
textFGCol = textFGCol .. tHex[v.FgCol or self.fgColor]:rep(newItem:len())
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
self.parent:setText(obx, oby, text:sub(itemOffset+1, self.width+itemOffset))
|
||||||
|
self.parent:setBG(obx, oby, textBGCol:sub(itemOffset+1, self.width+itemOffset))
|
||||||
|
self.parent:setFG(obx, oby, textFGCol:sub(itemOffset+1, self.width+itemOffset))
|
||||||
|
end
|
||||||
|
self:setVisualChanged(false)
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
}
|
||||||
|
|
||||||
|
return setmetatable(object, base)
|
||||||
|
end
|
||||||
27
Basalt/objects/Pane.lua
Normal file
27
Basalt/objects/Pane.lua
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
local Object = require("Object")
|
||||||
|
|
||||||
|
return function(name)
|
||||||
|
-- Pane
|
||||||
|
local base = Object(name)
|
||||||
|
local objectType = "Pane"
|
||||||
|
|
||||||
|
local object = {
|
||||||
|
getType = function(self)
|
||||||
|
return objectType
|
||||||
|
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.width, self.height, self.bgColor)
|
||||||
|
self.parent:drawForegroundBox(obx, oby, self.width, self.height, self.bgColor)
|
||||||
|
end
|
||||||
|
self:setVisualChanged(false)
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return setmetatable(object, base)
|
||||||
|
end
|
||||||
647
Basalt/objects/Program.lua
Normal file
647
Basalt/objects/Program.lua
Normal file
@@ -0,0 +1,647 @@
|
|||||||
|
local Object = require("Object")
|
||||||
|
local tHex = require("tHex")
|
||||||
|
local process = require("process")
|
||||||
|
|
||||||
|
local sub = string.sub
|
||||||
|
|
||||||
|
return function(name, parent)
|
||||||
|
local base = Object(name)
|
||||||
|
local objectType = "Program"
|
||||||
|
base:setZIndex(5)
|
||||||
|
local object
|
||||||
|
|
||||||
|
local function createBasaltWindow(x, y, width, height)
|
||||||
|
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] = { parent:getBasaltInstance().getBaseTerm().getPaletteColour(c) }
|
||||||
|
end
|
||||||
|
|
||||||
|
local function createEmptyLines()
|
||||||
|
emptySpaceLine = (" "):rep(width)
|
||||||
|
for n = 0, 15 do
|
||||||
|
local nColor = 2 ^ n
|
||||||
|
local sHex = tHex[nColor]
|
||||||
|
emptyColorLines[nColor] = sHex:rep(width)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function recreateWindowArray()
|
||||||
|
createEmptyLines()
|
||||||
|
local emptyText = emptySpaceLine
|
||||||
|
local emptyFG = emptyColorLines[colors.white]
|
||||||
|
local emptyBG = emptyColorLines[colors.black]
|
||||||
|
for n = 1, height do
|
||||||
|
cacheT[n] = sub(cacheT[n] == nil and emptyText or cacheT[n] .. emptyText:sub(1, width - cacheT[n]:len()), 1, width)
|
||||||
|
cacheFG[n] = sub(cacheFG[n] == nil and emptyFG or cacheFG[n] .. emptyFG:sub(1, width - cacheFG[n]:len()), 1, width)
|
||||||
|
cacheBG[n] = sub(cacheBG[n] == nil and emptyBG or cacheBG[n] .. emptyBG:sub(1, width - cacheBG[n]:len()), 1, width)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
recreateWindowArray()
|
||||||
|
|
||||||
|
local function updateCursor()
|
||||||
|
if xCursor >= 1 and yCursor >= 1 and xCursor <= width and yCursor <= height 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 <= height then
|
||||||
|
if nStart <= width and nEnd >= 1 then
|
||||||
|
-- Modify line
|
||||||
|
if nStart == 1 and nEnd == width then
|
||||||
|
cacheT[yCursor] = sText
|
||||||
|
cacheFG[yCursor] = sTextColor
|
||||||
|
cacheBG[yCursor] = sBackgroundColor
|
||||||
|
else
|
||||||
|
local sClippedText, sClippedTextColor, sClippedBackgroundColor
|
||||||
|
if nStart < 1 then
|
||||||
|
local nClipStart = 1 - nStart + 1
|
||||||
|
local nClipEnd = width - nStart + 1
|
||||||
|
sClippedText = sub(sText, nClipStart, nClipEnd)
|
||||||
|
sClippedTextColor = sub(sTextColor, nClipStart, nClipEnd)
|
||||||
|
sClippedBackgroundColor = sub(sBackgroundColor, nClipStart, nClipEnd)
|
||||||
|
elseif nEnd > width then
|
||||||
|
local nClipEnd = width - nStart + 1
|
||||||
|
sClippedText = sub(sText, 1, nClipEnd)
|
||||||
|
sClippedTextColor = sub(sTextColor, 1, nClipEnd)
|
||||||
|
sClippedBackgroundColor = sub(sBackgroundColor, 1, nClipEnd)
|
||||||
|
else
|
||||||
|
sClippedText = sText
|
||||||
|
sClippedTextColor = sTextColor
|
||||||
|
sClippedBackgroundColor = sBackgroundColor
|
||||||
|
end
|
||||||
|
|
||||||
|
local sOldText = cacheT[yCursor]
|
||||||
|
local sOldTextColor = cacheFG[yCursor]
|
||||||
|
local sOldBackgroundColor = cacheBG[yCursor]
|
||||||
|
local sNewText, sNewTextColor, sNewBackgroundColor
|
||||||
|
if nStart > 1 then
|
||||||
|
local nOldEnd = nStart - 1
|
||||||
|
sNewText = sub(sOldText, 1, nOldEnd) .. sClippedText
|
||||||
|
sNewTextColor = sub(sOldTextColor, 1, nOldEnd) .. sClippedTextColor
|
||||||
|
sNewBackgroundColor = sub(sOldBackgroundColor, 1, nOldEnd) .. sClippedBackgroundColor
|
||||||
|
else
|
||||||
|
sNewText = sClippedText
|
||||||
|
sNewTextColor = sClippedTextColor
|
||||||
|
sNewBackgroundColor = sClippedBackgroundColor
|
||||||
|
end
|
||||||
|
if nEnd < width then
|
||||||
|
local nOldStart = nEnd + 1
|
||||||
|
sNewText = sNewText .. sub(sOldText, nOldStart, width)
|
||||||
|
sNewTextColor = sNewTextColor .. sub(sOldTextColor, nOldStart, width)
|
||||||
|
sNewBackgroundColor = sNewBackgroundColor .. sub(sOldBackgroundColor, nOldStart, width)
|
||||||
|
end
|
||||||
|
|
||||||
|
cacheT[yCursor] = sNewText
|
||||||
|
cacheFG[yCursor] = sNewTextColor
|
||||||
|
cacheBG[yCursor] = sNewBackgroundColor
|
||||||
|
end
|
||||||
|
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()), width), 1, width)
|
||||||
|
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()), width), 1, width)
|
||||||
|
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()), width), 1, width)
|
||||||
|
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 width, height
|
||||||
|
end;
|
||||||
|
|
||||||
|
getTextColor = function()
|
||||||
|
return fgColor
|
||||||
|
end;
|
||||||
|
getTextColour = function()
|
||||||
|
return fgColor
|
||||||
|
end;
|
||||||
|
|
||||||
|
basalt_resize = function(_width, _height)
|
||||||
|
width, height = _width, _height
|
||||||
|
recreateWindowArray()
|
||||||
|
end;
|
||||||
|
|
||||||
|
basalt_reposition = function(_x, _y)
|
||||||
|
x, y = _x, _y
|
||||||
|
end;
|
||||||
|
|
||||||
|
basalt_setVisible = function(vis)
|
||||||
|
visible = vis
|
||||||
|
end;
|
||||||
|
|
||||||
|
drawBackgroundBox = function(_x, _y, _width, _height, bgCol)
|
||||||
|
for n = 1, _height do
|
||||||
|
setBG(_x, _y + (n - 1), tHex[bgCol]:rep(_width))
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
drawForegroundBox = function(_x, _y, _width, _height, fgCol)
|
||||||
|
for n = 1, _height do
|
||||||
|
setFG(_x, _y + (n - 1), tHex[fgCol]:rep(_width))
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
drawTextBox = function(_x, _y, _width, _height, symbol)
|
||||||
|
for n = 1, _height do
|
||||||
|
setText(_x, _y + (n - 1), symbol:rep(_width))
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
|
||||||
|
writeText = function(_x, _y, text, bgCol, fgCol)
|
||||||
|
bgCol = bgCol or bgColor
|
||||||
|
fgCol = fgCol or fgColor
|
||||||
|
setText(x, _y, text)
|
||||||
|
setBG(_x, _y, tHex[bgCol]:rep(text:len()))
|
||||||
|
setFG(_x, _y, tHex[fgCol]:rep(text:len()))
|
||||||
|
end;
|
||||||
|
|
||||||
|
basalt_update = function()
|
||||||
|
if (parent ~= nil) then
|
||||||
|
for n = 1, height do
|
||||||
|
parent:setText(x, y + (n - 1), cacheT[n])
|
||||||
|
parent:setBG(x, y + (n - 1), cacheBG[n])
|
||||||
|
parent:setFG(x, y + (n - 1), cacheFG[n])
|
||||||
|
end
|
||||||
|
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, height do
|
||||||
|
local y = newY + offset
|
||||||
|
if y >= 1 and y <= height then
|
||||||
|
cacheT[newY] = cacheT[y]
|
||||||
|
cacheBG[newY] = cacheBG[y]
|
||||||
|
cacheFG[newY] = cacheFG[y]
|
||||||
|
else
|
||||||
|
cacheT[newY] = sEmptyText
|
||||||
|
cacheFG[newY] = sEmptyTextColor
|
||||||
|
cacheBG[newY] = sEmptyBackgroundColor
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if (visible) then
|
||||||
|
updateCursor()
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
isColor = function()
|
||||||
|
return parent:getBasaltInstance().getBaseTerm().isColor()
|
||||||
|
end;
|
||||||
|
|
||||||
|
isColour = function()
|
||||||
|
return parent:getBasaltInstance().getBaseTerm().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(width))
|
||||||
|
setBG(1, yCursor, tHex[bgColor]:rep(width))
|
||||||
|
setFG(1, yCursor, tHex[fgColor]:rep(width))
|
||||||
|
end
|
||||||
|
if (visible) then
|
||||||
|
updateCursor()
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
|
||||||
|
clear = function()
|
||||||
|
for n = 1, height do
|
||||||
|
setText(1, n, (" "):rep(width))
|
||||||
|
setBG(1, n, tHex[bgColor]:rep(width))
|
||||||
|
setFG(1, n, tHex[fgColor]:rep(width))
|
||||||
|
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
|
||||||
|
internalBlit(text, fgcol, bgcol)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return basaltwindow
|
||||||
|
end
|
||||||
|
|
||||||
|
base.width = 30
|
||||||
|
base.height = 12
|
||||||
|
local pWindow = createBasaltWindow(1, 1, base.width, base.height)
|
||||||
|
local curProcess
|
||||||
|
local paused = false
|
||||||
|
local queuedEvent = {}
|
||||||
|
|
||||||
|
object = {
|
||||||
|
getType = function(self)
|
||||||
|
return objectType
|
||||||
|
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, width, height)
|
||||||
|
base.setSize(self, width, height)
|
||||||
|
pWindow.basalt_resize(self.width, self.height)
|
||||||
|
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
|
||||||
|
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 _, value in pairs(events) do
|
||||||
|
curProcess:resume(value.event, table.unpack(value.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(nil, nil, true))
|
||||||
|
curProcess:resume(event, button, x - (absX - 1), y - (absY - 1))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
|
||||||
|
keyHandler = function(self, event, key)
|
||||||
|
base.keyHandler(self, event, key)
|
||||||
|
if (self:isFocused()) then
|
||||||
|
if (curProcess == nil) then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
if not (curProcess:isDead()) then
|
||||||
|
if not (paused) then
|
||||||
|
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.width - 1 and yCur + oby - 1 >= 1 and yCur + oby - 1 <= oby + self.height - 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 ~= "monitor_touch") 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.width - 1 and yCur + oby - 1 >= 1 and yCur + oby - 1 <= oby + self.height - 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 ~= "monitor_touch") 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)
|
||||||
|
if(self.bgColor~=false)then
|
||||||
|
self.parent:drawBackgroundBox(obx, oby, self.width, self.height, self.bgColor)
|
||||||
|
end
|
||||||
|
pWindow.basalt_update()
|
||||||
|
end
|
||||||
|
self:setVisualChanged(false)
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return setmetatable(object, base)
|
||||||
|
end
|
||||||
103
Basalt/objects/Progressbar.lua
Normal file
103
Basalt/objects/Progressbar.lua
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
local Object = require("Object")
|
||||||
|
local theme = require("theme")
|
||||||
|
|
||||||
|
return function(name)
|
||||||
|
-- Checkbox
|
||||||
|
local base = Object(name)
|
||||||
|
local objectType = "Progressbar"
|
||||||
|
|
||||||
|
local progress = 0
|
||||||
|
|
||||||
|
base:setZIndex(5)
|
||||||
|
base:setValue(false)
|
||||||
|
base.width = 25
|
||||||
|
base.height = 1
|
||||||
|
base.bgColor = theme.CheckboxBG
|
||||||
|
base.fgColor = theme.CheckboxFG
|
||||||
|
|
||||||
|
local activeBarColor = colors.black
|
||||||
|
local activeBarSymbol = ""
|
||||||
|
local activeBarSymbolCol = colors.white
|
||||||
|
local bgBarSymbol = ""
|
||||||
|
local direction = 0
|
||||||
|
|
||||||
|
local object = {
|
||||||
|
|
||||||
|
getType = function(self)
|
||||||
|
return objectType
|
||||||
|
end;
|
||||||
|
|
||||||
|
setDirection = function(self, dir)
|
||||||
|
direction = dir
|
||||||
|
return self
|
||||||
|
end;
|
||||||
|
|
||||||
|
setProgressBar = function(self, color, symbol, symbolcolor)
|
||||||
|
activeBarColor = color or activeBarColor
|
||||||
|
activeBarSymbol = symbol or activeBarSymbol
|
||||||
|
activeBarSymbolCol = symbolcolor or activeBarSymbolCol
|
||||||
|
return self
|
||||||
|
end;
|
||||||
|
|
||||||
|
setBackgroundSymbol = function(self, symbol)
|
||||||
|
bgBarSymbol = symbol:sub(1, 1)
|
||||||
|
return self
|
||||||
|
end;
|
||||||
|
|
||||||
|
setProgress = function(self, value)
|
||||||
|
if (value >= 0) and (value <= 100) and (progress ~= value) then
|
||||||
|
progress = value
|
||||||
|
self:setValue(progress)
|
||||||
|
if (progress == 100) then
|
||||||
|
self:progressDoneHandler()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end;
|
||||||
|
|
||||||
|
getProgress = function(self)
|
||||||
|
return progress
|
||||||
|
end;
|
||||||
|
|
||||||
|
onProgressDone = function(self, f)
|
||||||
|
self:registerEvent("progress_done", f)
|
||||||
|
return self
|
||||||
|
end;
|
||||||
|
|
||||||
|
progressDoneHandler = function(self)
|
||||||
|
self:sendEvent("progress_done", self)
|
||||||
|
end;
|
||||||
|
|
||||||
|
draw = function(self)
|
||||||
|
if (base.draw(self)) then
|
||||||
|
if (self.parent ~= nil) then
|
||||||
|
local obx, oby = self:getAnchorPosition()
|
||||||
|
if(self.bgColor~=false)then self.parent:drawBackgroundBox(obx, oby, self.width, self.height, self.bgColor) end
|
||||||
|
if(bgBarSymbol~="")then self.parent:drawTextBox(obx, oby, self.width, self.height, bgBarSymbol) end
|
||||||
|
if(self.fgColor~=false)then self.parent:drawForegroundBox(obx, oby, self.width, self.height, self.fgColor) end
|
||||||
|
if (direction == 1) then
|
||||||
|
self.parent:drawBackgroundBox(obx, oby, self.width, self.height / 100 * progress, activeBarColor)
|
||||||
|
self.parent:drawForegroundBox(obx, oby, self.width, self.height / 100 * progress, activeBarSymbolCol)
|
||||||
|
self.parent:drawTextBox(obx, oby, self.width, self.height / 100 * progress, activeBarSymbol)
|
||||||
|
elseif (direction == 2) then
|
||||||
|
self.parent:drawBackgroundBox(obx, oby + math.ceil(self.height - self.height / 100 * progress), self.width, self.height / 100 * progress, activeBarColor)
|
||||||
|
self.parent:drawForegroundBox(obx, oby + math.ceil(self.height - self.height / 100 * progress), self.width, self.height / 100 * progress, activeBarSymbolCol)
|
||||||
|
self.parent:drawTextBox(obx, oby + math.ceil(self.height - self.height / 100 * progress), self.width, self.height / 100 * progress, activeBarSymbol)
|
||||||
|
elseif (direction == 3) then
|
||||||
|
self.parent:drawBackgroundBox(obx + math.ceil(self.width - self.width / 100 * progress), oby, self.width / 100 * progress, self.height, activeBarColor)
|
||||||
|
self.parent:drawForegroundBox(obx + math.ceil(self.width - self.width / 100 * progress), oby, self.width / 100 * progress, self.height, activeBarSymbolCol)
|
||||||
|
self.parent:drawTextBox(obx + math.ceil(self.width - self.width / 100 * progress), oby, self.width / 100 * progress, self.height, activeBarSymbol)
|
||||||
|
else
|
||||||
|
self.parent:drawBackgroundBox(obx, oby, self.width / 100 * progress, self.height, activeBarColor)
|
||||||
|
self.parent:drawForegroundBox(obx, oby, self.width / 100 * progress, self.height, activeBarSymbolCol)
|
||||||
|
self.parent:drawTextBox(obx, oby, self.width / 100 * progress, self.height, activeBarSymbol)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
self:setVisualChanged(false)
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return setmetatable(object, base)
|
||||||
|
end
|
||||||
129
Basalt/objects/Radio.lua
Normal file
129
Basalt/objects/Radio.lua
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
local Object = require("Object")
|
||||||
|
local theme = require("theme")
|
||||||
|
local utils = require("utils")
|
||||||
|
|
||||||
|
return function(name)
|
||||||
|
local base = Object(name)
|
||||||
|
local objectType = "Radio"
|
||||||
|
base.width = 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 objectType
|
||||||
|
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;
|
||||||
|
|
||||||
|
getAll = function(self)
|
||||||
|
return list
|
||||||
|
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 key, value in pairs(list) do
|
||||||
|
if (value == selected) then
|
||||||
|
return key
|
||||||
|
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")and(button==1))or(event=="monitor_touch") then
|
||||||
|
if (#list > 0) then
|
||||||
|
for _, value in pairs(list) do
|
||||||
|
if (obx + value.x - 1 <= x) and (obx + value.x - 1 + value.text:len() + 2 >= x) and (oby + value.y - 1 == y) then
|
||||||
|
self:setValue(value)
|
||||||
|
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
|
||||||
|
return false
|
||||||
|
end;
|
||||||
|
|
||||||
|
draw = function(self)
|
||||||
|
if (base.draw(self)) then
|
||||||
|
if (self.parent ~= nil) then
|
||||||
|
local obx, oby = self:getAnchorPosition()
|
||||||
|
for _, value in pairs(list) do
|
||||||
|
if (value == self:getValue()) then
|
||||||
|
if (align == "left") then
|
||||||
|
self.parent:writeText(value.x + obx - 1, value.y + oby - 1, symbol, boxSelectedBG, boxSelectedFG)
|
||||||
|
self.parent:writeText(value.x + 2 + obx - 1, value.y + oby - 1, value.text, itemSelectedBG, itemSelectedFG)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
self.parent:drawBackgroundBox(value.x + obx - 1, value.y + oby - 1, 1, 1, self.bgColor)
|
||||||
|
self.parent:writeText(value.x + 2 + obx - 1, value.y + oby - 1, value.text, value.bgCol, value.fgCol)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
self:setVisualChanged(false)
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
}
|
||||||
|
|
||||||
|
return setmetatable(object, base)
|
||||||
|
end
|
||||||
133
Basalt/objects/Scrollbar.lua
Normal file
133
Basalt/objects/Scrollbar.lua
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
local Object = require("Object")
|
||||||
|
local theme = require("theme")
|
||||||
|
|
||||||
|
return function(name)
|
||||||
|
local base = Object(name)
|
||||||
|
local objectType = "Scrollbar"
|
||||||
|
|
||||||
|
base.width = 1
|
||||||
|
base.height = 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.height
|
||||||
|
local index = 1
|
||||||
|
local symbolSize = 1
|
||||||
|
|
||||||
|
local object = {
|
||||||
|
getType = function(self)
|
||||||
|
return objectType
|
||||||
|
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.height - (symbolSize - 1))) - (maxValue / (self.height - (symbolSize - 1))))
|
||||||
|
elseif (barType == "horizontal") then
|
||||||
|
self:setValue(index - 1 * (maxValue / (self.width - (symbolSize - 1))) - (maxValue / (self.width - (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))or(event=="monitor_touch") then
|
||||||
|
if (barType == "horizontal") then
|
||||||
|
for _index = 0, self.width do
|
||||||
|
if (obx + _index == x) and (oby <= y) and (oby + self.height > y) then
|
||||||
|
index = math.min(_index + 1, self.width - (symbolSize - 1))
|
||||||
|
self:setValue(maxValue / self.width * (index))
|
||||||
|
self:setVisualChanged()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if (barType == "vertical") then
|
||||||
|
for _index = 0, self.height do
|
||||||
|
if (oby + _index == y) and (obx <= x) and (obx + self.width > x) then
|
||||||
|
index = math.min(_index + 1, self.height - (symbolSize - 1))
|
||||||
|
self:setValue(maxValue / self.height * (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.height or self.width) - (symbolSize - 1))
|
||||||
|
self:setValue(maxValue / (barType == "vertical" and self.height or self.width) * 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.width - (index + symbolSize - 1)), self.bgColor, self.fgColor)
|
||||||
|
end
|
||||||
|
|
||||||
|
if (barType == "vertical") then
|
||||||
|
for n = 0, self.height - 1 do
|
||||||
|
|
||||||
|
if (index == n + 1) then
|
||||||
|
for curIndexOffset = 0, math.min(symbolSize - 1, self.height) 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
|
||||||
|
self:setVisualChanged(false)
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
}
|
||||||
|
|
||||||
|
return setmetatable(object, base)
|
||||||
|
end
|
||||||
132
Basalt/objects/Slider.lua
Normal file
132
Basalt/objects/Slider.lua
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
local Object = require("Object")
|
||||||
|
local theme = require("theme")
|
||||||
|
|
||||||
|
return function(name)
|
||||||
|
local base = Object(name)
|
||||||
|
local objectType = "Slider"
|
||||||
|
|
||||||
|
base.width = 8
|
||||||
|
base.height = 1
|
||||||
|
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.width
|
||||||
|
local index = 1
|
||||||
|
local symbolSize = 1
|
||||||
|
|
||||||
|
local object = {
|
||||||
|
getType = function(self)
|
||||||
|
return objectType
|
||||||
|
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.height - (symbolSize - 1))) - (maxValue / (self.height - (symbolSize - 1))))
|
||||||
|
elseif (barType == "horizontal") then
|
||||||
|
self:setValue(index - 1 * (maxValue / (self.width - (symbolSize - 1))) - (maxValue / (self.width - (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))or(event=="monitor_touch") then
|
||||||
|
if (barType == "horizontal") then
|
||||||
|
for _index = 0, self.width do
|
||||||
|
if (obx + _index == x) and (oby <= y) and (oby + self.height > y) then
|
||||||
|
index = math.min(_index + 1, self.width - (symbolSize - 1))
|
||||||
|
self:setValue(maxValue / self.width * (index))
|
||||||
|
self:setVisualChanged()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if (barType == "vertical") then
|
||||||
|
for _index = 0, self.height do
|
||||||
|
if (oby + _index == y) and (obx <= x) and (obx + self.width > x) then
|
||||||
|
index = math.min(_index + 1, self.height - (symbolSize - 1))
|
||||||
|
self:setValue(maxValue / self.height * (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.height or self.width) - (symbolSize - 1))
|
||||||
|
self:setValue(maxValue / (barType == "vertical" and self.height or self.width) * 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.width - (index + symbolSize - 1)), self.bgColor, self.fgColor)
|
||||||
|
end
|
||||||
|
|
||||||
|
if (barType == "vertical") then
|
||||||
|
for n = 0, self.height - 1 do
|
||||||
|
|
||||||
|
if (index == n + 1) then
|
||||||
|
for curIndexOffset = 0, math.min(symbolSize - 1, self.height) 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
|
||||||
|
self:setVisualChanged(false)
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
}
|
||||||
|
|
||||||
|
return setmetatable(object, base)
|
||||||
|
end
|
||||||
71
Basalt/objects/Switch.lua
Normal file
71
Basalt/objects/Switch.lua
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
local Object = require("Object")
|
||||||
|
local theme = require("theme")
|
||||||
|
|
||||||
|
return function(name)
|
||||||
|
local base = Object(name)
|
||||||
|
local objectType = "Switch"
|
||||||
|
|
||||||
|
base.width = 2
|
||||||
|
base.height = 1
|
||||||
|
base.bgColor = colors.lightGray
|
||||||
|
base.fgColor = colors.gray
|
||||||
|
base:setValue(false)
|
||||||
|
base:setZIndex(5)
|
||||||
|
|
||||||
|
local bgSymbol = colors.black
|
||||||
|
local inactiveBG = colors.red
|
||||||
|
local activeBG = colors.green
|
||||||
|
|
||||||
|
local object = {
|
||||||
|
getType = function(self)
|
||||||
|
return objectType
|
||||||
|
end;
|
||||||
|
|
||||||
|
setSymbolColor = function(self, symbolColor)
|
||||||
|
bgSymbol = symbolColor
|
||||||
|
self:setVisualChanged()
|
||||||
|
return self
|
||||||
|
end;
|
||||||
|
|
||||||
|
setActiveBackground = function(self, bgcol)
|
||||||
|
activeBG = bgcol
|
||||||
|
self:setVisualChanged()
|
||||||
|
return self
|
||||||
|
end;
|
||||||
|
|
||||||
|
setInactiveBackground = function(self, bgcol)
|
||||||
|
inactiveBG = bgcol
|
||||||
|
self:setVisualChanged()
|
||||||
|
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") and (button == 1))or(event=="monitor_touch") then
|
||||||
|
self:setValue(not self:getValue())
|
||||||
|
end
|
||||||
|
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.width, self.height, self.bgColor)
|
||||||
|
if(self:getValue())then
|
||||||
|
self.parent:drawBackgroundBox(obx, oby, 1, self.height, activeBG)
|
||||||
|
self.parent:drawBackgroundBox(obx+1, oby, 1, self.height, bgSymbol)
|
||||||
|
else
|
||||||
|
self.parent:drawBackgroundBox(obx, oby, 1, self.height, bgSymbol)
|
||||||
|
self.parent:drawBackgroundBox(obx+1, oby, 1, self.height, inactiveBG)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
self:setVisualChanged(false)
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
}
|
||||||
|
|
||||||
|
return setmetatable(object, base)
|
||||||
|
end
|
||||||
344
Basalt/objects/Textfield.lua
Normal file
344
Basalt/objects/Textfield.lua
Normal file
@@ -0,0 +1,344 @@
|
|||||||
|
local Object = require("Object")
|
||||||
|
local theme = require("theme")
|
||||||
|
|
||||||
|
return function(name)
|
||||||
|
local base = Object(name)
|
||||||
|
local objectType = "Textfield"
|
||||||
|
local hIndex, wIndex, textX, textY = 1, 1, 1, 1
|
||||||
|
|
||||||
|
local lines = { "" }
|
||||||
|
local keyWords = { [colors.purple] = { "break" } }
|
||||||
|
|
||||||
|
base.width = 20
|
||||||
|
base.height = 8
|
||||||
|
base.bgColor = theme.textfieldBG
|
||||||
|
base.fgColor = theme.textfieldFG
|
||||||
|
base:setZIndex(5)
|
||||||
|
|
||||||
|
local object = {
|
||||||
|
getType = function(self)
|
||||||
|
return objectType
|
||||||
|
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;
|
||||||
|
|
||||||
|
addKeyword = function(self, keyword, color)
|
||||||
|
|
||||||
|
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 == keys.backspace) then
|
||||||
|
-- on backspace
|
||||||
|
if (lines[textY] == "") then
|
||||||
|
if (textY > 1) then
|
||||||
|
table.remove(lines, textY)
|
||||||
|
textX = lines[textY - 1]:len() + 1
|
||||||
|
wIndex = textX - self.width + 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.width + 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 == keys.delete) then
|
||||||
|
-- on delete
|
||||||
|
if (textX > lines[textY]:len()) then
|
||||||
|
if (lines[textY + 1] ~= nil) then
|
||||||
|
lines[textY] = lines[textY] .. lines[textY + 1]
|
||||||
|
table.remove(lines, textY + 1)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
lines[textY] = lines[textY]:sub(1, textX - 1) .. lines[textY]:sub(textX + 1, lines[textY]:len())
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if (key == keys.enter) 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.height) then
|
||||||
|
hIndex = hIndex + 1
|
||||||
|
end
|
||||||
|
self:setValue("")
|
||||||
|
end
|
||||||
|
|
||||||
|
if (key == keys.up) 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.width + 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 == keys.down) 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.height) then
|
||||||
|
hIndex = hIndex + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if (key == keys.right) 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.width + wIndex) then
|
||||||
|
wIndex = textX - self.width + 1
|
||||||
|
end
|
||||||
|
if (wIndex < 1) then
|
||||||
|
wIndex = 1
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
if (key == keys.left) then
|
||||||
|
-- arrow left
|
||||||
|
textX = textX - 1
|
||||||
|
if (textX >= 1) then
|
||||||
|
if (textX < wIndex) or (textX >= self.width + 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.width + 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.width + 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.width - 1) then
|
||||||
|
cursorX = self.x + self.width - 1
|
||||||
|
end
|
||||||
|
local cursorY = (textY - hIndex < self.height 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")or(event=="monitor_touch") 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, self.fgColor)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if (event == "mouse_drag") 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, self.fgColor)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if (event == "mouse_scroll") then
|
||||||
|
hIndex = hIndex + button
|
||||||
|
if (hIndex > #lines - (self.height - 1)) then
|
||||||
|
hIndex = #lines - (self.height - 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.width) and (oby + textY - hIndex >= oby and oby + textY - hIndex <= oby + self.height) then
|
||||||
|
self.parent:setCursor(true, anchx + textX - wIndex, anchy + textY - hIndex, self.fgColor)
|
||||||
|
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()
|
||||||
|
if(self.bgColor~=false)then
|
||||||
|
self.parent:drawBackgroundBox(obx, oby, self.width, self.height, self.bgColor)
|
||||||
|
end
|
||||||
|
if(self.fgColor~=false)then
|
||||||
|
self.parent:drawForegroundBox(obx, oby, self.width, self.height, self.fgColor)
|
||||||
|
end
|
||||||
|
for n = 1, self.height do
|
||||||
|
local text = ""
|
||||||
|
if (lines[n + hIndex - 1] ~= nil) then
|
||||||
|
text = lines[n + hIndex - 1]
|
||||||
|
end
|
||||||
|
text = text:sub(wIndex, self.width + wIndex - 1)
|
||||||
|
local space = self.width - text:len()
|
||||||
|
if (space < 0) then
|
||||||
|
space = 0
|
||||||
|
end
|
||||||
|
text = text .. string.rep(" ", space)
|
||||||
|
self.parent:setText(obx, oby + n - 1, text)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
self:setVisualChanged(false)
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
}
|
||||||
|
|
||||||
|
return setmetatable(object, base)
|
||||||
|
end
|
||||||
69
Basalt/objects/Thread.lua
Normal file
69
Basalt/objects/Thread.lua
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
return function(name)
|
||||||
|
local object
|
||||||
|
local objectType = "Thread"
|
||||||
|
|
||||||
|
local func
|
||||||
|
local cRoutine
|
||||||
|
local isActive = false
|
||||||
|
|
||||||
|
object = {
|
||||||
|
name = name,
|
||||||
|
getType = function(self)
|
||||||
|
return objectType
|
||||||
|
end;
|
||||||
|
getZIndex = function(self)
|
||||||
|
return 1
|
||||||
|
end;
|
||||||
|
getName = function(self)
|
||||||
|
return self.name
|
||||||
|
end;
|
||||||
|
|
||||||
|
start = function(self, f)
|
||||||
|
if (f == nil) then
|
||||||
|
error("Function provided to thread 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("Thread Error Occurred - " .. 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("Thread Error Occurred - " .. result)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
isActive = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
object.__index = object
|
||||||
|
|
||||||
|
return object
|
||||||
|
end
|
||||||
77
Basalt/objects/Timer.lua
Normal file
77
Basalt/objects/Timer.lua
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
local basaltEvent = require("basaltEvent")
|
||||||
|
|
||||||
|
return function(name)
|
||||||
|
local objectType = "Timer"
|
||||||
|
|
||||||
|
local timer = 0
|
||||||
|
local savedRepeats = 0
|
||||||
|
local repeats = 0
|
||||||
|
local timerObj
|
||||||
|
local eventSystem = basaltEvent()
|
||||||
|
local timerIsActive = false
|
||||||
|
|
||||||
|
local object = {
|
||||||
|
name = name,
|
||||||
|
getType = function(self)
|
||||||
|
return objectType
|
||||||
|
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)
|
||||||
|
if(timerIsActive)then
|
||||||
|
os.cancelTimer(timerObj)
|
||||||
|
end
|
||||||
|
repeats = savedRepeats
|
||||||
|
timerObj = os.startTimer(timer)
|
||||||
|
timerIsActive = true
|
||||||
|
return self
|
||||||
|
end;
|
||||||
|
|
||||||
|
isActive = function(self)
|
||||||
|
return timerIsActive
|
||||||
|
end;
|
||||||
|
|
||||||
|
cancel = function(self)
|
||||||
|
if (timerObj ~= nil) then
|
||||||
|
os.cancelTimer(timerObj)
|
||||||
|
end
|
||||||
|
timerIsActive = false
|
||||||
|
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 and timerIsActive 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
|
||||||
47
Basalt/objects/example.lua
Normal file
47
Basalt/objects/example.lua
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
local Object = require("Object")
|
||||||
|
|
||||||
|
return function(name)
|
||||||
|
local base = Object(name) -- this will load the base object class, it is necessary if you want to make a visual object, otherwise you dont need that.
|
||||||
|
local objectType = "Example" -- here is the object type, make sure it is the same as the file name - this way you can also make sure its unique
|
||||||
|
|
||||||
|
-- here you could set some default values, but its not necessary, it doesn't matter if you call the functions or change the values directly, maybe i should change that
|
||||||
|
--i guess its better if you call functions base:setBackground, base:setSize and so on.
|
||||||
|
base.width = 12
|
||||||
|
base.height = 1
|
||||||
|
base.bgColor = colors.lightGray
|
||||||
|
base.fgColor = colors.gray
|
||||||
|
base:setValue(false)
|
||||||
|
base:setZIndex(5) -- if you want to change the zIndex always use the function
|
||||||
|
|
||||||
|
local object = { -- here you start your unique object class, please always make sure a getType exists!
|
||||||
|
getType = function(self)
|
||||||
|
return objectType
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
mouseClickHandler = function(self, event, button, x, y) -- this is your extended mouseClickHandler, if you want something to happen if the user clicks on that
|
||||||
|
if (base.mouseClickHandler(self, event, button, x, y)) then -- here you access the base class mouseClickHandler it will return true if the user really clicks on the object
|
||||||
|
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition()) --getAnchorPosition is obviously for returning the x and y coords changed by the anchor system, absolute position explains itself i guess
|
||||||
|
if ((event == "mouse_click") or (event == "mouse_drag")) and (button == 1) then
|
||||||
|
--here you can create your logic
|
||||||
|
end
|
||||||
|
return true -- please always return true if base.mouseClickHandler also returns true, otherwise your object wont get focused.
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
|
||||||
|
draw = function(self) -- if your object is visual, you will need a draw function
|
||||||
|
if (base.draw(self)) then
|
||||||
|
if (self.parent ~= nil) then
|
||||||
|
local obx, oby = self:getAnchorPosition()
|
||||||
|
--self.parent:drawBackgroundbox(obx, oby, self.width, self.height, self.bgColor) -- changes the background color of that object
|
||||||
|
--self.parent:drawForegroundbox(obx, oby, self.width, self.height, self.fgColor) -- changes the foreground (textcolor) color of that object
|
||||||
|
--self.parent:writeText(obx, oby, "Some Text", self.bgColor, self.fgColor) -- writes something on the screen, also able to change its bgcolor and fgcolor
|
||||||
|
|
||||||
|
--the draw functions always gets called after something got visually changed. I am always redrawing the entire screen, but only if something has changed.
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
}
|
||||||
|
|
||||||
|
return setmetatable(object, base) -- required
|
||||||
|
end
|
||||||
22
Basalt/theme.lua
Normal file
22
Basalt/theme.lua
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
return { -- The default theme for basalt!
|
||||||
|
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,
|
||||||
|
}
|
||||||
18
README.md
18
README.md
@@ -9,3 +9,21 @@ Basalt is still under developement and you may find bugs!
|
|||||||
|
|
||||||
Check out the [wiki](https://basalt.madefor.cc/) for information<br>
|
Check out the [wiki](https://basalt.madefor.cc/) for information<br>
|
||||||
If you have questions, feel free to join the discord server: [https://discord.gg/yM7kndJdJJ](https://discord.gg/yM7kndJdJJ)
|
If you have questions, feel free to join the discord server: [https://discord.gg/yM7kndJdJJ](https://discord.gg/yM7kndJdJJ)
|
||||||
|
|
||||||
|
## Changelogs
|
||||||
|
From now on we will add changelogs to every changes:
|
||||||
|
|
||||||
|
#### Version 2:
|
||||||
|
Note: You won't get any changes for now, so don't redownload the project! (:
|
||||||
|
- reworked the filesystem, now we use require instead of loadfile
|
||||||
|
- from now on the single file will be complied on the end users computer
|
||||||
|
- prepared everything for an advanced installer
|
||||||
|
|
||||||
|
#### Version 1:
|
||||||
|
- created Basalt
|
||||||
|
- added many objects (buttons, checkbox, labels, programs, switch, radio, lists, dropdowns, input, textfields, images, menubar, animations, threads, timers, progressbar, scrollbar, slider, pane)
|
||||||
|
- added bigfont
|
||||||
|
- added blittle
|
||||||
|
- added coroutine management
|
||||||
|
- added advanced event system
|
||||||
|
|
||||||
|
|||||||
32
projectFiles.txt
Normal file
32
projectFiles.txt
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
libraries/basaltDraw.lua
|
||||||
|
libraries/basaltEvent.lua
|
||||||
|
libraries/bigfont.lua
|
||||||
|
libraries/logSystem.lua
|
||||||
|
libraries/process.lua
|
||||||
|
libraries/tHex.lua
|
||||||
|
libraries/utils.lua
|
||||||
|
objects/Animations.lua
|
||||||
|
objects/Button.lua
|
||||||
|
objects/Checkbox.lua
|
||||||
|
objects/Dropdown.lua
|
||||||
|
objects/Image.lua
|
||||||
|
objects/Input.lua
|
||||||
|
objects/Label.lua
|
||||||
|
objects/List.lua
|
||||||
|
objects/Menubar.lua
|
||||||
|
objects/Pane.lua
|
||||||
|
objects/Program.lua
|
||||||
|
objects/Progressbar.lua
|
||||||
|
objects/Radio.lua
|
||||||
|
objects/Scrollbar.lua
|
||||||
|
objects/Slider.lua
|
||||||
|
objects/Switch.lua
|
||||||
|
objects/Textfield.lua
|
||||||
|
objects/Thread.lua
|
||||||
|
objects/Timer.lua
|
||||||
|
loadObjects.lua
|
||||||
|
theme.lua
|
||||||
|
main.lua
|
||||||
|
init.lua
|
||||||
|
Frame.lua
|
||||||
|
Object.lua
|
||||||
Reference in New Issue
Block a user