18 Commits

Author SHA1 Message Date
Robert Jelic
c0fab23cef Small update to 1.6.4
- added bimg support
- reworked graphic object
- added blit for drawsystem (makes drawing bit faster
- added bimg lib
- reworked image object
- fixed thread bug
2022-11-23 17:32:06 +01:00
Robert Jelic
7609708507 Merge branch 'master' of https://github.com/Pyroxenium/Basalt 2022-11-23 17:11:33 +01:00
Robert Jelic
e2f2a2871d Improved event system
Updated the event system to the current dev branch
2022-11-23 17:11:21 +01:00
Robert Jelic
37dde881ad Small bugfix for frames
Small bugfix for frames when using setZIndex after objects got added. Reason was because the frame didn't add the events to it's parent.
2022-11-22 18:28:03 +01:00
Robert Jelic
8f2e191fe3 Border Bugfix for Buttons
Small visual fix for buttons, when using borders
2022-11-21 06:23:13 +01:00
Robert Jelic
15d8cb3781 Update Object.lua
cancels other events - should never have been there
2022-11-14 06:13:23 +01:00
Robert Jelic
8acb673f74 small hotfix for source project 2022-11-04 21:18:32 +01:00
Robert Jelic
cfdca639db Docs update
some docs update for the new installer
2022-10-31 17:30:11 +01:00
Robert Jelic
b34cdd8383 Small install.lua fix
Small fix to the web version
2022-10-31 00:41:57 +01:00
Robert Jelic
a74b8a3d9f Some smaller changed
some changes for testing improved installer
2022-10-31 00:27:59 +01:00
Robert Jelic
ef480c3998 changed index.html
-added edit-on-github
-added copy code
-added image zoom
- changed search depth from 6 to 2
2022-10-26 00:24:22 +02:00
Robert Jelic
c3e97ae516 Docs -> frames
Updated the frame object in docs
2022-10-26 00:19:00 +02:00
Robert Jelic
d78bb4d141 Docs - panes
changed panes to make it more clear why they exist
2022-10-21 21:13:09 +02:00
Robert Jelic
ab72f244ed Updated some formatting
Updated formatting for object
2022-10-20 21:05:29 +02:00
Robert Jelic
4352d36831 Small docs update
- added searchbar
- added :remove method @Object
2022-10-20 20:20:25 +02:00
Robert Jelic
04ad97ccbe Small program fix 2022-10-20 06:22:14 +02:00
Robert Jelic
6b2433e0a1 Whoops 2022-10-13 20:59:49 +02:00
Robert Jelic
bf1b008084 Docs update
Some more stuff for docs
2022-10-09 14:00:35 +02:00
99 changed files with 16125 additions and 727 deletions

View File

@@ -49,6 +49,8 @@ return function(name, parent, pTerm, basalt)
local activeEvents = {}
local colorTheme = {}
base:setZIndex(10)
local basaltDraw = BasaltDraw(termObject)
@@ -81,6 +83,7 @@ return function(name, parent, pTerm, basalt)
end
local function getObject(name)
if(type(name)~="string")then name = name.name end
for _, value in pairs(objects) do
for _, b in pairs(value) do
if (b:getName() == name) then
@@ -240,11 +243,11 @@ return function(name, parent, pTerm, basalt)
end
return false
end
local math = math
local function stringToNumber(str)
local ok, err = pcall(load("return " .. str))
local ok, result = pcall(load("return " .. str, "", nil, {math=math}))
if not(ok)then error(str.." is not a valid dynamic code") end
return load("return " .. str)()
return result
end
local function newDynamicValue(_, obj, str)
@@ -327,8 +330,13 @@ return function(name, parent, pTerm, basalt)
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("dynamicValueEvent", self)
if(basalt.getDynamicValueEventSetting())then
if (value.eventHandler ~= nil) then
value:eventHandler("basalt_dynamicvalue", self)
end
end
if (value.customEventHandler ~= nil) then
value:customEventHandler("basalt_resize", self)
end
end
end
@@ -340,17 +348,49 @@ return function(name, parent, pTerm, basalt)
return dynamicValues[id][1]
end
local function calculateMaxScroll(self)
local function getVerticalScrollAmount(self)
local amount = 0
for _, value in pairs(objects) do
for _, b in pairs(value) do
if(b.getHeight~=nil)and(b.getY~=nil)then
local h, y = b:getHeight(), b:getY()
if (h + y - self:getHeight() > scrollAmount) then
scrollAmount = max(h + y - self:getHeight(), 0)
if(b:getType()=="Dropdown")then
local h, y = b:getHeight(), b:getY()
local wD, hD = b:getDropdownSize()
h = h + hD - 1
if (h + y - self:getHeight() >= amount) then
amount = max(h + y - self:getHeight(), 0)
end
else
local h, y = b:getHeight(), b:getY()
if (h + y - self:getHeight() >= amount) then
amount = max(h + y - self:getHeight(), 0)
end
end
end
end
end
return amount
end
local function getHorizontalScrollAmount(self)
local amount = 0
for _, value in pairs(objects) do
for _, b in pairs(value) do
if(b.getWidth~=nil)and(b.getX~=nil)then
local h, y = b:getWidth(), b:getX()
if (h + y - self:getWidth() >= amount) then
amount = max(h + y - self:getWidth(), 0)
end
end
end
end
return amount
end
local function calculateMaxScroll(self)
if(autoScroll)then
scrollAmount = getVerticalScrollAmount(self)
end
end
object = {
@@ -373,13 +413,27 @@ return function(name, parent, pTerm, basalt)
return objectType
end;
setZIndex = function(self, newIndex)
base.setZIndex(self, newIndex)
for k,v in pairs(activeEvents)do
if(v)then
self.parent:addEvent(k, self)
end
end
return self
end,
setFocusedObject = function(self, obj)
if(focusedObject~=obj)then
if(focusedObject~=nil)then
focusedObject:loseFocusHandler()
if(getObject(focusedObject)~=nil)then
focusedObject:loseFocusHandler()
end
end
if(obj~=nil)then
obj:getFocusHandler()
if(getObject(obj)~=nil)then
obj:getFocusHandler()
end
end
focusedObject = obj
end
@@ -398,8 +452,8 @@ return function(name, parent, pTerm, basalt)
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("basalt_resize", value, self)
if (value.customEventHandler ~= nil) then
value:customEventHandler("basalt_resize", self)
end
end
end
@@ -423,17 +477,34 @@ return function(name, parent, pTerm, basalt)
return theme[name] or (self.parent~=nil and self.parent:getTheme(name) or basalt.getTheme(name))
end,
setPosition = function(self, x, y, rel)
base.setPosition(self, x, y, rel)
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("basalt_reposition", value, self)
getThemeColor = function(self, col)
return col~=nil and colorTheme[col] or colorTheme
end,
setThemeColor = function(self, col, ...)
if(self.parent==nil)then
if(self==basalt.getActiveFrame())then
if(type(col)=="string")then
colorTheme[col] = ...
termObject.setPaletteColor(type(col)=="number" and col or colors[col], ...)
elseif(type(col)=="table")then
for k,v in pairs(col)do
colorTheme[k] = v
if(type(v)=="number")then
termObject.setPaletteColor(type(k)=="number" and k or colors[k], v)
else
local r,g,b = table.unpack(v)
termObject.setPaletteColor(type(k)=="number" and k or colors[k], r,g,b)
end
end
end
end
end
return self
end,
setPosition = function(self, x, y, rel)
base.setPosition(self, x, y, rel)
self:recalculateDynamicValues()
return self
end;
@@ -459,7 +530,9 @@ return function(name, parent, pTerm, basalt)
removeFocusedObject = function(self)
if(focusedObject~=nil)then
focusedObject:loseFocusHandler()
if(getObject(focusedObject)~=nil)then
focusedObject:loseFocusHandler()
end
end
focusedObject = nil
return self
@@ -527,10 +600,26 @@ return function(name, parent, pTerm, basalt)
return autoScroll and calculateMaxScroll(self) or scrollAmount
end,
getCalculatedVerticalScroll = getVerticalScrollAmount,
getCalculatedHorizontalScroll = getHorizontalScrollAmount,
show = function(self)
base.show(self)
if(self.parent==nil)then
basalt.setActiveFrame(self)
for k,v in pairs(colors)do
if(type(v)=="number")then
termObject.setPaletteColor(v, colors.packRGB(term.nativePaletteColor((v))))
end
end
for k,v in pairs(colorTheme)do
if(type(v)=="number")then
termObject.setPaletteColor(type(k)=="number" and k or colors[k], v)
else
local r,g,b = table.unpack(v)
termObject.setPaletteColor(type(k)=="number" and k or colors[k], r,g,b)
end
end
if(isMonitor)and not(isGroupedMonitor)then
basalt.setMonitorFrame(monSide, self)
elseif(isGroupedMonitor)then
@@ -545,7 +634,7 @@ return function(name, parent, pTerm, basalt)
hide = function (self)
base.hide(self)
if(self.parent==nil)then
if(activeFrame == self)then activeFrame = nil end -- bug activeFrame always nil
if(activeFrame == self)then activeFrame = nil end
if(isMonitor)and not(isGroupedMonitor)then
if(basalt.getMonitorFrame(monSide) == self)then
basalt.setActiveFrame(nil)
@@ -794,9 +883,6 @@ return function(name, parent, pTerm, basalt)
self:mouseHandler(1, p2, p3, true)
end
end
if (event == "terminate")and(self.parent==nil)then
basalt.stop()
end
end,
mouseHandler = function(self, button, x, y, _, side)
@@ -881,8 +967,8 @@ return function(name, parent, pTerm, basalt)
self:updateDraw()
end
end
self:removeFocusedObject()
if(yOffset==cache)then return false end
self:removeFocusedObject()
return true
end
return false

View File

@@ -1,9 +1,13 @@
local basaltEvent = require("basaltEvent")
local utils = require("utils")
local module = require("module")
local images = module("images")
local split = utils.splitString
local numberFromString = utils.numberFromString
local xmlValue = utils.getValueFromXML
local unpack,sub = table.unpack,string.sub
return function(name)
-- Base object
local objectType = "Object" -- not changeable
@@ -30,6 +34,13 @@ return function(name)
local isDragging = false
local dragStartX, dragStartY, dragXOffset, dragYOffset = 0, 0, 0, 0
local bimg
local texture
local textureId = 1
local textureTimerId
local textureMode
local infinitePlay = true
local draw = true
local activeEvents = {}
@@ -97,8 +108,8 @@ return function(name)
setValuesByXMLData = function(self, data)
local baseFrame = self:getBaseFrame()
if(xmlValue("x", data)~=nil)then self:setPosition(xmlValue("x", data), self.y) end
if(xmlValue("y", data)~=nil)then self:setPosition(self.x, xmlValue("y", data)) end
if(xmlValue("x", data)~=nil)then self:setPosition(xmlValue("x", data), self:getY()) end
if(xmlValue("y", data)~=nil)then self:setPosition(self:getX(), xmlValue("y", data)) end
if(xmlValue("width", data)~=nil)then self:setSize(xmlValue("width", data), self.height) end
if(xmlValue("height", data)~=nil)then self:setSize(self.width, xmlValue("height", data)) end
if(xmlValue("bg", data)~=nil)then self:setBackground(colors[xmlValue("bg", data)]) end
@@ -195,11 +206,13 @@ return function(name)
return self
end;
setValue = function(self, _value)
setValue = function(self, _value, valueChangedHandler)
if (value ~= _value) then
value = _value
self:updateDraw()
self:valueChangedHandler()
if(valueChangedHandler~=false)then
self:valueChangedHandler()
end
end
return self
end;
@@ -245,7 +258,7 @@ return function(name)
end
self.parent:recalculateDynamicValues()
end
eventSystem:sendEvent("basalt_reposition", self)
self:customEventHandler("basalt_reposition")
self:updateDraw()
return self
end;
@@ -288,24 +301,27 @@ return function(name)
end
self.parent:recalculateDynamicValues()
end
eventSystem:sendEvent("basalt_resize", self)
if(bimg~=nil)and(textureMode=="stretch")then
texture = images.resizeBIMG(bimg, self:getSize())[textureId]
end
self:customEventHandler("basalt_resize")
self:updateDraw()
return self
end;
end,
getHeight = function(self)
return type(self.height) == "number" and self.height or math.floor(self.height[1]+0.5)
end;
end,
getWidth = function(self)
return type(self.width) == "number" and self.width or math.floor(self.width[1]+0.5)
end;
end,
getSize = function(self)
return self:getWidth(), self:getHeight()
end;
end,
calculateDynamicValues = function(self)
calculateDynamicValues = function(self)
if(type(self.width)=="table")then self.width:calculate() end
if(type(self.height)=="table")then self.height:calculate() end
if(type(self.x)=="table")then self.x:calculate() end
@@ -320,12 +336,38 @@ return function(name)
self.bgSymbolColor = symbolCol or self.bgSymbolColor
self:updateDraw()
return self
end;
end,
setTexture = function(self, tex, mode, infPlay)
if(type(tex)=="string")then
bimg = images.loadImageAsBimg(tex)
elseif(type(tex)=="table")then
bimg = tex
end
if(bimg.animated)then
local t = bimg[textureId].duration or bimg.secondsPerFrame or 0.2
textureTimerId = os.startTimer(t)
self.parent:addEvent("other_event", self)
activeEvents["other_event"] = true
end
infinitePlay = infPlay==false and false or true
textureId = 1
textureMode = mode or "normal"
if(textureMode=="stretch")then
texture = images.resizeBIMG(bimg, self:getSize())[1]
else
texture = bimg[1]
end
self:updateDraw()
return self
end,
setTransparent = function(self, color)
self.transparentColor = color or false
self.bgSymbol = false
self.bgSymbolColor = false
if(color~=false)then
self.bgSymbol = false
self.bgSymbolColor = false
end
self:updateDraw()
return self
end;
@@ -403,18 +445,50 @@ return function(name)
local w,h = self:getSize()
local wP,hP = self.parent:getSize()
if(x+w<1)or(x>wP)or(y+h<1)or(y>hP)then return false end
if(self.transparentColor~=false)then
self.parent:drawForegroundBox(x, y, w, h, self.transparentColor)
end
if(self.bgColor~=false)then
self.parent:drawBackgroundBox(x, y, w, h, self.bgColor)
end
if(self.bgSymbol~=false)then
self.parent:drawTextBox(x, y, w, h, self.bgSymbol)
if(self.bgSymbol~=" ")then
self.parent:drawForegroundBox(x, y, w, h, self.bgSymbolColor)
if(self.transparentColor~=false)then
self.parent:drawForegroundBox(x, y, w, h, self.transparentColor)
end
if(self.bgColor~=false)then
self.parent:drawBackgroundBox(x, y, w, h, self.bgColor)
end
if(self.bgSymbol~=false)then
self.parent:drawTextBox(x, y, w, h, self.bgSymbol)
if(self.bgSymbol~=" ")then
self.parent:drawForegroundBox(x, y, w, h, self.bgSymbolColor)
end
end
if(texture~=nil)then
if(textureMode=="center")then
local tW,tH = #texture[1][1],#texture
local xO = tW < w and math.floor((w-tW)/2) or 0
local yO = tH < h and math.floor((h-tH)/2) or 0
local sL = tW<w and 1 or math.floor((tW-w)/2)
local eL = tW<w and w or w - math.floor((w-tW)/2+0.5)-1
local sH = tH<h and 1 or math.floor((tH-h)/2)
local eH = tH<h and h or h - math.floor((h-tH)/2+0.5)-1
local yTex = 1
for k=sH,#texture do
if(texture[k]~=nil)then
local t, f, b = unpack(texture[k])
t = sub(t, sL,eL)
f = sub(f, sL,eL)
b = sub(b, sL,eL)
self.parent:blit(x+xO, y+yTex-1+yO, t, f, b)
end
yTex = yTex + 1
if(k==eH)then break end
end
else
for k,v in pairs(texture)do
local t, f, b = unpack(v)
t = sub(t, 1,w)
f = sub(f, 1,w)
b = sub(b, 1,w)
self.parent:blit(x, y+k-1, t, f, b)
if(k==h)then break end
end
end
end
end
if(shadow)then
self.parent:drawBackgroundBox(x+1, y+h, w, 1, shadowColor)
self.parent:drawBackgroundBox(x+w, y+1, 1, h, shadowColor)
@@ -425,11 +499,10 @@ return function(name)
local bgCol = self.bgColor
if(borderColors["left"]~=false)then
self.parent:drawTextBox(x, y, 1, h, "\149")
if(bgCol~=false)then self.parent:drawBackgroundBox(x, y, 1, h, self.bgColor) end
if(bgCol~=false)then self.parent:drawBackgroundBox(x, y, 1, h, bgCol) end
self.parent:drawForegroundBox(x, y, 1, h, borderColors["left"])
end
if(borderColors["top"]~=false)then
self.parent:drawTextBox(x, y, w, 1, "\131")
if(bgCol~=false)then self.parent:drawBackgroundBox(x, y, w, 1, self.bgColor) end
self.parent:drawForegroundBox(x, y, w, 1, borderColors["top"])
@@ -792,7 +865,7 @@ return function(name)
mouseHandler = function(self, button, x, y, isMon)
if(self:isCoordsInObject(x, y))then
local objX, objY = self:getAbsolutePosition()
local val = eventSystem:sendEvent("mouse_click", self, "mouse_click", button, x - (objX-1), y - (objY-1), isMon)
local val = eventSystem:sendEvent("mouse_click", self, "mouse_click", button, x - (objX-1), y - (objY-1), x, y, isMon)
if(val==false)then return false end
if(self.parent~=nil)then
self.parent:setFocusedObject(self)
@@ -809,12 +882,12 @@ return function(name)
isDragging = false
if(isClicked)then
local objX, objY = self:getAbsolutePosition()
local val = eventSystem:sendEvent("mouse_release", self, "mouse_release", button, x - (objX-1), y - (objY-1))
local val = eventSystem:sendEvent("mouse_release", self, "mouse_release", button, x - (objX-1), y - (objY-1), x, y)
isClicked = false
end
if(self:isCoordsInObject(x, y))then
local objX, objY = self:getAbsolutePosition()
local val = eventSystem:sendEvent("mouse_up", self, "mouse_up", button, x - (objX-1), y - (objY-1))
local val = eventSystem:sendEvent("mouse_up", self, "mouse_up", button, x - (objX-1), y - (objY-1), x, y)
if(val==false)then return false end
return true
end
@@ -906,8 +979,42 @@ return function(name)
eventSystem:sendEvent("value_changed", self, value)
end;
eventHandler = function(self, event, p1, p2, p3, p4)
local val = eventSystem:sendEvent("other_event", self, event, p1, p2, p3, p4)
eventHandler = function(self, event, ...)
local args = {...}
if(event=="timer")and(args[1]==textureTimerId)then
if(bimg[textureId+1]~=nil)then
textureId = textureId + 1
if(textureMode=="stretch")then
texture = images.resizeBIMG(bimg, self:getSize())[textureId]
else
texture = bimg[textureId]
end
local t = bimg[textureId].duration or bimg.secondsPerFrame or 0.2
textureTimerId = os.startTimer(t)
else
if(infinitePlay)then
textureId = 1
if(textureMode=="stretch")then
texture = images.resizeBIMG(bimg, self:getSize())[1]
else
texture = bimg[1]
end
local t = bimg[1].duration or bimg.secondsPerFrame or 0.2
textureTimerId = os.startTimer(t)
end
end
self:updateDraw()
end
local val = eventSystem:sendEvent("other_event", self, event, ...)
if(val~=nil)then return val end
end;
customEventHandler = function(self, event, ...)
if(bimg~=nil)and(textureMode=="stretch")and(event=="basalt_resize")then
texture = images.resizeBIMG(bimg, self:getSize())[textureId]
self:updateDraw()
end
local val = eventSystem:sendEvent("custom_event", self, event, ...)
if(val~=nil)then return val end
return true
end;

View File

@@ -1,9 +1,16 @@
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")..string.format(format, package.path, curDir.."/objects",curDir.."/objects")
if not(packed)then
local defaultPath = package.path
local format = "path;/path/?.lua;/path/?/init.lua;"
local main = format:gsub("path", curDir)
local objFolder = format:gsub("path", curDir.."/objects")
local libFolder = format:gsub("path", curDir.."/libraries")
package.path = main..objFolder..libFolder..defaultPath
end
local Basalt = require("main")
package.path = defaultPath

View File

@@ -126,6 +126,52 @@ return function(drawTerm)
end
end
local function blit(x, y, t, fg, bg)
if(#t == #fg)or(#t == #bg)then
if (y >= 1) and (y <= height) then
if (x + t:len() > 0) and (x <= width) then
local oldCacheT = cacheT[y]
local oldCacheFG = cacheFG[y]
local oldCacheBG = cacheBG[y]
local newCacheT, newCacheFG, newCacheBG
local nEnd = x + #t - 1
if (x < 1) then
local startN = 1 - x + 1
local endN = width - x + 1
t = sub(t, startN, endN)
fg = sub(fg, startN, endN)
bg = sub(bg, startN, endN)
elseif (nEnd > width) then
local endN = width - x + 1
t = sub(t, 1, endN)
fg = sub(fg, 1, endN)
bg = sub(bg, 1, endN)
end
if (x > 1) then
local endN = x - 1
newCacheT = sub(oldCacheT, 1, endN) .. t
newCacheFG = sub(oldCacheFG, 1, endN) .. fg
newCacheBG = sub(oldCacheBG, 1, endN) .. bg
else
newCacheT = t
newCacheFG = fg
newCacheBG = bg
end
if nEnd < width then
newCacheT = newCacheT .. sub(oldCacheT, nEnd + 1, width)
newCacheFG = newCacheFG .. sub(oldCacheFG, nEnd + 1, width)
newCacheBG = newCacheBG .. sub(oldCacheBG, nEnd + 1, width)
end
cacheT[y] = newCacheT
cacheFG[y] = newCacheFG
cacheBG[y] = newCacheBG
end
end
end
end
local drawHelper = {
setSize = function(w, h)
width, height = w, h
@@ -147,6 +193,10 @@ return function(drawTerm)
setFG(x, y, colorStr)
end;
blit = function(x, y, t, fg, bg)
blit(x, y, t, fg, bg)
end,
drawBackgroundBox = function(x, y, width, height, bgCol)
for n = 1, height do
setBG(x, y + (n - 1), rep(tHex[bgCol], width))

381
Basalt/libraries/bimg.lua Normal file
View File

@@ -0,0 +1,381 @@
local sub,rep = string.sub,string.rep
local function frame(base, manager)
local w, h = 0, 0
local t,fg,bg = {}, {}, {}
local x, y = 1,1
local data = {}
local function recalculateSize()
for y=1,h do
if(t[y]==nil)then
t[y] = rep(" ", w)
else
t[y] = t[y]..rep(" ", w-#t[y])
end
if(fg[y]==nil)then
fg[y] = rep("0", w)
else
fg[y] = fg[y]..rep("0", w-#fg[y])
end
if(bg[y]==nil)then
bg[y] = rep("f", w)
else
bg[y] = bg[y]..rep("f", w-#bg[y])
end
end
end
local addText = function(text, _x, _y)
x = _x or x
y = _y or y
if(t[y]==nil)then
t[y] = rep(" ", x-1)..text..rep(" ", w-(#text+x))
else
t[y] = sub(t[y], 1, x-1)..rep(" ", x-#t[y])..text..sub(t[y], x+#text, w)
end
if(#t[y]>w)then w = #t[y] end
if(y > h)then h = y end
manager.updateSize(w, h)
end
local addBg = function(b, _x, _y)
x = _x or x
y = _y or y
if(bg[y]==nil)then
bg[y] = rep("f", x-1)..b..rep("f", w-(#b+x))
else
bg[y] = sub(bg[y], 1, x-1)..rep("f", x-#bg[y])..b..sub(bg[y], x+#b, w)
end
if(#bg[y]>w)then w = #bg[y] end
if(y > h)then h = y end
manager.updateSize(w, h)
end
local addFg = function(f, _x, _y)
x = _x or x
y = _y or y
if(fg[y]==nil)then
fg[y] = rep("0", x-1)..f..rep("0", w-(#f+x))
else
fg[y] = sub(fg[y], 1, x-1)..rep("0", x-#fg[y])..f..sub(fg[y], x+#f, w)
end
if(#fg[y]>w)then w = #fg[y] end
if(y > h)then h = y end
manager.updateSize(w, h)
end
local function setFrame(frm)
data = {}
t, fg, bg = {}, {}, {}
for k,v in pairs(base)do
if(type(k)=="string")then
data[k] = v
else
t[k], fg[k], bg[k] = v[1], v[2], v[3]
end
end
manager.updateSize(w, h)
end
if(base~=nil)then
w = #base[1][1]
h = #base
setFrame(base)
end
return {
recalculateSize = recalculateSize,
setFrame = setFrame,
getFrame = function()
local f = {}
for k,v in pairs(t)do
table.insert(f, {v, fg[k], bg[k]})
end
for k,v in pairs(data)do
f[k] = v
end
return f, w, h
end,
getImage = function()
local i = {}
for k,v in pairs(t)do
table.insert(i, {v, fg[k], bg[k]})
end
return i
end,
setFrameData = function(key, value)
if(value~=nil)then
data[key] = value
else
if(type(key)=="table")then
data = key
end
end
end,
setFrameImage = function(imgData)
for k,v in pairs(imgData.t)do
t[k] = imgData.t[k]
fg[k] = imgData.fg[k]
bg[k] = imgData.bg[k]
end
end,
getFrameImage = function()
return {t = t, fg = fg, bg = bg}
end,
getFrameData = function(key)
return (key~= nil and data[key] or data)
end,
blit = function(text, fgCol, bgCol, x, y)
addText(text, x, y)
addFg(fgCol, x, y)
addBg(bgCol, x, y)
end,
text = addText,
fg = addFg,
bg = addBg,
getSize = function()
return w, h
end,
setSize = function(_w, _h)
local nt,nfg,nbg = {}, {}, {}
for _y=1,_h do
if(t[_y]~=nil)then
nt[_y] = sub(t[_y], 1, _w)..rep(" ", _w - w)
else
nt[_y] = rep(" ", _w)
end
if(fg[_y]~=nil)then
nfg[_y] = sub(fg[_y], 1, _w)..rep("0", _w - w)
else
nfg[_y] = rep("0", _w)
end
if(bg[_y]~=nil)then
nbg[_y] = sub(bg[_y], 1, _w)..rep("f", _w - w)
else
nbg[_y] = rep("f", _w)
end
end
t, fg, bg = nt, nfg, nbg
w, h = _w, _h
end,
}
end
return function(img)
local frames = {}
local metadata = {creator="Bimg Library by NyoriE", date=os.date("!%Y-%m-%dT%TZ")}
local width,height = 0, 0
local manager = {}
local function addFrame(id, data)
id = id or #frames+1
table.insert(frames, id, frame(data, manager))
if(data==nil)then
frames[id].setSize(width, height)
end
end
local function removeFrame(id)
table.remove(frames, id or #frames)
end
local function moveFrame(id, dir)
local f = frames[id]
if(f~=nil)then
local newId = id+dir
if(newId>=1)and(newId<=#frames)then
table.remove(frames, id)
table.insert(frames, newId, f)
end
end
end
manager = {
updateSize = function(w, h, force)
local changed = force==true and true or false
if(w > width)then changed = true width = w end
if(h > height)then changed = true height = h end
if(changed)then
for k,v in pairs(frames)do
v.setSize(width, height)
v.recalculateSize()
end
end
end,
text = function(frame, text, x, y)
local f = frames[frame]
if(f==nil)then
f = addFrame(frame)
end
f.text(text, x, y)
end,
fg = function(frame, fg, x, y)
local f = frames[frame]
if(f==nil)then
f = addFrame(frame)
end
f.fg(fg, x, y)
end,
bg = function(frame, bg, x, y)
local f = frames[frame]
if(f==nil)then
f = addFrame(frame)
end
f.bg(bg, x, y)
end,
blit = function(frame, text, fg, bg, x, y)
local f = frames[frame]
if(f==nil)then
f = addFrame(frame)
end
f.blit(text, fg, bg, x, y)
end,
setSize = function(w, h)
width = w
height = h
for k,v in pairs(frames)do
v.setSize(w, h)
end
end,
getFrame = function(id)
if(frames[id]~=nil)then
return frames[id].getFrame()
end
end,
getFrameObjects = function()
return frames
end,
getFrames = function()
local f = {}
for k,v in pairs(frames)do
local frame = v.getFrame()
table.insert(f, frame)
end
return f
end,
getFrameObject = function(id)
return frames[id]
end,
addFrame = function(id)
local f = frame()
if(#frames<=1)then
if(metadata.animated==nil)then
metadata.animated = true
end
if(metadata.secondsPerFrame==nil)then
metadata.secondsPerFrame = 0.2
end
end
addFrame(id)
return f
end,
removeFrame = function(id)
removeFrame(id)
if(#frames<=1)then
if(metadata.animated==nil)then
metadata.animated = true
end
if(metadata.secondsPerFrame==nil)then
metadata.secondsPerFrame = 0.2
end
end
end,
moveFrame = moveFrame,
setFrameData = function(id, key, value)
if(frames[id]~=nil)then
frames[id].setFrameData(key, value)
end
end,
getFrameData = function(id, key)
return frames[id]~=nil and frames[id].getFrameData(key)
end,
getSize = function()
return width, height
end,
setAnimation = function(anim)
metadata.animation = anim
end,
setMetadata = function(key, val)
if(val~=nil)then
metadata[key] = val
else
if(type(key)=="table")then
metadata = key
end
end
end,
getMetadata = function(key)
return key~=nil and metadata[key] or metadata
end,
createBimg = function()
local bimg = {}
for k,v in pairs(frames)do
local f = v.getFrame()
table.insert(bimg, f)
end
for k,v in pairs(metadata)do
bimg[k] = v
end
bimg.width = width
bimg.height = height
return bimg
end,
}
if(img~=nil)then
for k,v in pairs(img)do
if(type(k)=="string")then
metadata[k] = v
else
addFrame(k, v)
end
end
if(metadata.width==nil)or(metadata.height==nil)then
for k,v in pairs(frames)do
local w, h = v.getSize()
if(w>width)then w = width end
if(h>height)then h = height end
end
manager.updateSize(width, height, true)
end
else
addFrame(1)
end
return manager
end

View File

@@ -0,0 +1,89 @@
local sub,floor = string.sub,math.floor
local function loadNFPAsBimg(path)
return {[1]={{}, {}, paintutils.loadImage(path)}}, "bimg"
end
local function loadNFP(path)
return paintutils.loadImage(path), "nfp"
end
local function loadBIMG(path)
local f = fs.open(path, "rb")
local content = textutils.unserialize(f.readAll())
f.close()
if(content~=nil)then
return content, "bimg"
end
end
local function loadBBF(path)
end
local function loadBBFAsBimg(path)
end
local function loadImage(path, f)
if(f==nil)then
if(path:find(".bimg"))then
return loadBIMG(path)
elseif(path:find(".bbf"))then
return loadBBF(path)
else
return loadNFP(path)
end
end
-- ...
end
local function loadImageAsBimg(path, f)
if(f==nil)then
if(path:find(".bimg"))then
return loadBIMG(path)
elseif(path:find(".bbf"))then
return loadBBFAsBimg(path)
else
return loadNFPAsBimg(path)
end
end
end
local function resizeBIMG(source, w, h)
local oW, oH = source.width or #source[1][1][1], source.height or #source[1]
local newImg = {}
for k,v in pairs(source)do
if(type(k)=="number")then
local frame = {}
for y=1, h do
local xT,xFG,xBG = "","",""
local yR = floor(y / h * oH + 0.5)
if(v[yR]~=nil)then
for x=1, w do
local xR = floor(x / w * oW + 0.5)
xT = xT..sub(v[yR][1], xR,xR)
xFG = xFG..sub(v[yR][2], xR,xR)
xBG = xBG..sub(v[yR][3], xR,xR)
end
table.insert(frame, {xT, xFG, xBG})
end
end
table.insert(newImg, k, frame)
else
newImg[k] = v
end
end
newImg.width = w
newImg.height = h
return newImg
end
return {
loadNFP = loadNFP,
loadBIMG = loadBIMG,
loadImage = loadImage,
resizeBIMG = resizeBIMG,
loadImageAsBimg = loadImageAsBimg,
}

View File

@@ -2,14 +2,32 @@ local processes = {}
local process = {}
local processId = 0
function process:new(path, window, ...)
local newPackage = dofile("rom/modules/main/cc/require.lua").make
function process:new(path, window, newEnv, ...)
local args = {...}
local newP = setmetatable({ path = path }, { __index = self })
newP.window = window
window.current = term.current
window.redirect = term.redirect
newP.processId = processId
if(type(path)=="string")then
newP.coroutine = coroutine.create(function()
shell.execute(path, table.unpack(args))
local pPath = shell.resolveProgram(path)
local env = setmetatable(newEnv, {__index=_ENV})
env.shell = shell
env.basaltProgram=true
env.arg = {[0]=path, table.unpack(args)}
env.require, env.package = newPackage(env, fs.getDir(pPath))
if(fs.exists(pPath))then
local file = fs.open(pPath, "r")
local content = file.readAll()
file.close()
local program = load(content, path, "bt", env)
if(program~=nil)then
return program()
end
end
end)
elseif(type(path)=="function")then
newP.coroutine = coroutine.create(function()
@@ -24,17 +42,21 @@ function process:new(path, window, ...)
end
function process:resume(event, ...)
local cur = term.current()
term.redirect(self.window)
if(self.filter~=nil)then
if(event~=self.filter)then return end
self.filter=nil
end
local ok, result = coroutine.resume(self.coroutine, event, ...)
if ok then
self.filter = result
else
error(result)
printError(result)
end
term.redirect(cur)
return ok, result
end
function process:isDead()

View File

@@ -1,3 +1,5 @@
local sub = string.sub
local splitString = function(str, sep)
if sep == nil then
sep = "%s"
@@ -9,6 +11,74 @@ local splitString = function(str, sep)
return t
end
local relations = {[0] = {8, 4, 3, 6, 5}, {4, 14, 8, 7}, {6, 10, 8, 7}, {9, 11, 8, 0}, {1, 14, 8, 0}, {13, 12, 8, 0}, {2, 10, 8, 0}, {15, 8, 10, 11, 12, 14},
{0, 7, 1, 9, 2, 13}, {3, 11, 8, 7}, {2, 6, 7, 15}, {9, 3, 7, 15}, {13, 5, 7, 15}, {5, 12, 8, 7}, {1, 4, 7, 15}, {7, 10, 11, 12, 14}}
local colourNum, exponents, colourChar = {}, {}, {}
for i = 0, 15 do exponents[2^i] = i end
do
local hex = "0123456789abcdef"
for i = 1, 16 do
colourNum[hex:sub(i, i)] = i - 1
colourNum[i - 1] = hex:sub(i, i)
colourChar[hex:sub(i, i)] = 2 ^ (i - 1)
colourChar[2 ^ (i - 1)] = hex:sub(i, i)
local thisRel = relations[i - 1]
for i = 1, #thisRel do thisRel[i] = 2 ^ thisRel[i] end
end
end
local function getBestColourMatch(usage)
local lastCol = relations[exponents[usage[#usage][1]]]
for j = 1, #lastCol do
local thisRelation = lastCol[j]
for i = 1, #usage - 1 do if usage[i][1] == thisRelation then return i end end
end
return 1
end
local function colsToChar(pattern, totals)
if not totals then
local newPattern = {}
totals = {}
for i = 1, 6 do
local thisVal = pattern[i]
local thisTot = totals[thisVal]
totals[thisVal], newPattern[i] = thisTot and (thisTot + 1) or 1, thisVal
end
pattern = newPattern
end
local usage = {}
for key, value in pairs(totals) do usage[#usage + 1] = {key, value} end
if #usage > 1 then
-- Reduce the chunk to two colours:
while #usage > 2 do
table.sort(usage, function (a, b) return a[2] > b[2] end)
local matchToInd, usageLen = getBestColourMatch(usage), #usage
local matchFrom, matchTo = usage[usageLen][1], usage[matchToInd][1]
for i = 1, 6 do if pattern[i] == matchFrom then
pattern[i] = matchTo
usage[matchToInd][2] = usage[matchToInd][2] + 1
end end
usage[usageLen] = nil
end
-- Convert to character. Adapted from oli414's function:
-- http://www.computercraft.info/forums2/index.php?/topic/25340-cc-176-easy-drawing-characters/
local data = 128
for i = 1, #pattern - 1 do if pattern[i] ~= pattern[6] then data = data + 2^(i-1) end end
return string.char(data), colourChar[usage[1][1] == pattern[6] and usage[2][1] or usage[1][1]], colourChar[pattern[6]]
else
-- Solid colour character:
return "\128", colourChar[pattern[1]], colourChar[pattern[1]]
end
end
return {
getTextHorizontalAlign = function(text, width, textAlign, replaceChar)
text = string.sub(text, 1, width)
@@ -117,4 +187,36 @@ uuid = function()
end
return uuid()
end,
array = function(arraysize, hashsize)
return load("return {" .. ("nil,"):rep(arraysize) .. ("[0]=nil,"):rep(hashsize) .. "}")()
end,
shrink = function(image, bgCol)
local results, width, height, bgCol = {{}, {}, {}}, 0, #image + #image % 3, bgCol or colours.black
for i = 1, #image do if #image[i] > width then width = #image[i] end end
for y = 0, height - 1, 3 do
local cRow, tRow, bRow, counter = {}, {}, {}, 1
for x = 0, width - 1, 2 do
-- Grab a 2x3 chunk:
local pattern, totals = {}, {}
for yy = 1, 3 do for xx = 1, 2 do
pattern[#pattern + 1] = (image[y + yy] and image[y + yy][x + xx]) and (image[y + yy][x + xx] == 0 and bgCol or image[y + yy][x + xx]) or bgCol
totals[pattern[#pattern]] = totals[pattern[#pattern]] and (totals[pattern[#pattern]] + 1) or 1
end end
cRow[counter], tRow[counter], bRow[counter] = colsToChar(pattern, totals)
counter = counter + 1
end
results[1][#results[1] + 1], results[2][#results[2] + 1], results[3][#results[3] + 1] = table.concat(cRow), table.concat(tRow), table.concat(bRow)
end
results.width, results.height = #results[1][1], #results[1]
return results
end,
}

View File

@@ -10,7 +10,7 @@ local moveThrottle = 300
local dragThrottle = 50
local baseTerm = term.current()
local version = "1.6.2"
local version = "1.6.4"
local projectDirectory = fs.getDir(table.pack(...)[2] or "")
@@ -23,13 +23,26 @@ if not term.isColor or not term.isColor() then
error('Basalt requires an advanced (golden) computer to run.', 0)
end
local defaultColors = {}
for k,v in pairs(colors)do
if(type(v)=="number")then
defaultColors[k] = {baseTerm.getPaletteColor(v)}
end
end
local function stop()
updaterActive = false
baseTerm.clear()
baseTerm.setCursorPos(1, 1)
for k,v in pairs(colors)do
if(type(v)=="number")then
baseTerm.setPaletteColor(v, colors.packRGB(table.unpack(defaultColors[k])))
end
end
end
local basaltError = function(errMsg)
local function basaltError(errMsg)
baseTerm.clear()
baseTerm.setBackgroundColor(colors.black)
baseTerm.setTextColor(colors.red)
@@ -79,6 +92,10 @@ local getTheme = function(name)
end
local bInstance = {
getDynamicValueEventSetting = function()
return basalt.dynamicValueEvents
end,
getMainFrame = function()
return mainFrame
end,
@@ -176,8 +193,8 @@ end
local stopped, moveX, moveY = nil, nil, nil
local moveTimer = nil
local function mouseMoveEvent(stp, x, y)
stopped, moveX, moveY = stopped, x, y
local function mouseMoveEvent(_, stp, x, y)
stopped, moveX, moveY = stp, x, y
if(moveTimer==nil)then
moveTimer = os.startTimer(moveThrottle/1000)
end
@@ -197,7 +214,7 @@ local function dragHandlerTimer()
activeFrame = mainFrame
end
local function mouseDragEvent(b, x, y)
local function mouseDragEvent(_, b, x, y)
btn, dragX, dragY = b, x, y
if(dragThrottle<50)then
dragHandlerTimer()
@@ -208,79 +225,75 @@ local function mouseDragEvent(b, x, y)
end
end
local function basaltUpdateEvent(event, p1, p2, p3, p4)
if(basaltEvent:sendEvent("basaltEventCycle", event, p1, p2, p3, p4)==false)then return end
local function basaltUpdateEvent(event, ...)
local a = {...}
if(basaltEvent:sendEvent("basaltEventCycle", event, ...)==false)then return end
if(event=="terminate")then basalt.stop() end
if(mainFrame~=nil)then
if (event == "mouse_click") then
mainFrame:mouseHandler(p1, p2, p3, false)
activeFrame = mainFrame
elseif (event == "mouse_drag") then
mouseDragEvent(p1, p2, p3)
elseif (event == "mouse_up") then
mainFrame:mouseUpHandler(p1, p2, p3, p4)
activeFrame = mainFrame
elseif (event == "mouse_scroll") then
mainFrame:scrollHandler(p1, p2, p3, p4)
activeFrame = mainFrame
elseif (event == "mouse_move") then
mouseMoveEvent(p1, p2, p3)
local mouseEvents = {
mouse_click = mainFrame.mouseHandler,
mouse_up = mainFrame.mouseUpHandler,
mouse_scroll = mainFrame.scrollHandler,
mouse_drag = mouseDragEvent,
mouse_move = mouseMoveEvent,
}
local mouseEvent = mouseEvents[event]
if(mouseEvent~=nil)then
mouseEvent(mainFrame, ...)
drawFrames()
return
end
end
if(event == "monitor_touch") then
if(monFrames[p1]~=nil)then
monFrames[p1]:mouseHandler(1, p2, p3, true)
monFrames[p1]:mouseHandler(1, a[2], a[3], true)
activeFrame = monFrames[p1]
end
if(count(monGroups)>0)then
for k,v in pairs(monGroups)do
v[1]:mouseHandler(1, p2, p3, true, p1)
v[1]:mouseHandler(1, a[2], a[3], true, a[1])
end
end
drawFrames()
return
end
if(event == "char")then
if(activeFrame~=nil)then
activeFrame:charHandler(p1)
end
end
if(event == "key_up")then
if(activeFrame~=nil)then
activeFrame:keyUpHandler(p1)
end
activeKey[p1] = false
end
if(event == "key")then
if(activeFrame~=nil)then
activeFrame:keyHandler(p1, p2)
end
activeKey[p1] = true
end
if(event == "terminate")then
if(activeFrame~=nil)then
activeFrame:eventHandler(event)
if(updaterActive==false)then return end
end
end
if(event~="mouse_click")and(event~="mouse_up")and(event~="mouse_scroll")and(event~="mouse_drag")and(event~="mouse_move")and(event~="key")and(event~="key_up")and(event~="char")and(event~="terminate")then
if(event=="timer")and(p1==moveTimer)then
moveHandlerTimer()
elseif(event=="timer")and(p1==dragTimer)then
dragHandlerTimer()
else
for k, v in pairs(frames) do
v:eventHandler(event, p1, p2, p3, p4)
if(activeFrame~=nil)then
local keyEvents = {
char = activeFrame.charHandler,
key = activeFrame.keyHandler,
key_up = activeFrame.keyUpHandler,
}
local keyEvent = keyEvents[event]
if(keyEvent~=nil)then
if(event == "key")then
activeKey[a[1]] = true
elseif(event == "key_up")then
activeKey[a[1]] = false
end
keyEvent(activeFrame, ...)
drawFrames()
return
end
end
handleSchedules(event, p1, p2, p3, p4)
if(event=="timer")and(a[1]==moveTimer)then
moveHandlerTimer()
elseif(event=="timer")and(a[1]==dragTimer)then
dragHandlerTimer()
else
for k, v in pairs(frames) do
v:eventHandler(event, ...)
end
end
handleSchedules(event, ...)
drawFrames()
end
basalt = {
logging = false,
dynamicValueEvents = false,
setTheme = setTheme,
getTheme = getTheme,
drawFrames = drawFrames,
@@ -337,9 +350,9 @@ basalt = {
end
end,
update = function(event, p1, p2, p3, p4)
update = function(event, ...)
if (event ~= nil) then
local ok, err = xpcall(basaltUpdateEvent, debug.traceback, event, p1, p2, p3, p4)
local ok, err = xpcall(basaltUpdateEvent, debug.traceback, event, ...)
if not(ok)then
basaltError(err)
return

4
Basalt/module.lua Normal file
View File

@@ -0,0 +1,4 @@
return function(path)
local exists, content = pcall(require, path)
return exists and content or nil
end

View File

@@ -60,8 +60,9 @@ return function(name)
for n = 1, h do
if (n == verticalAlign) then
self.parent:setText(obx, oby + (n - 1), utils.getTextHorizontalAlign(self:getValue(), w, textHorizontalAlign))
self.parent:setFG(obx, oby + (n - 1), utils.getTextHorizontalAlign(tHex[self.fgColor]:rep(self:getValue():len()), w, textHorizontalAlign))
local val = self:getValue()
self.parent:setText(obx + (w/2-val:len()/2), oby + (n - 1), utils.getTextHorizontalAlign(val, val:len(), textHorizontalAlign))
self.parent:setFG(obx + (w/2-val:len()/2), oby + (n - 1), utils.getTextHorizontalAlign(tHex[self.fgColor]:rep(val:len()), val:len(), textHorizontalAlign))
end
end
end

View File

@@ -84,7 +84,7 @@ return function(name)
clear = function(self)
list = {}
self:setValue({})
self:setValue({}, false)
self:updateDraw()
return self
end;
@@ -101,7 +101,7 @@ return function(name)
end;
selectItem = function(self, index)
self:setValue(list[index] or {})
self:setValue(list[index] or {}, false)
self:updateDraw()
return self
end;
@@ -109,7 +109,7 @@ return function(name)
setSelectedItem = function(self, bgCol, fgCol, active)
itemSelectedBG = bgCol or self.bgColor
itemSelectedFG = fgCol or self.fgColor
selectionColorActive = active
selectionColorActive = active~=nil and active
self:updateDraw()
return self
end;
@@ -120,6 +120,10 @@ return function(name)
return self
end,
getDropdownSize = function(self)
return dropdownW, dropdownH
end,
mouseHandler = function(self, button, x, y)
if (isOpened) then
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition())

214
Basalt/objects/Graphic.lua Normal file
View File

@@ -0,0 +1,214 @@
local Object = require("Object")
local tHex = require("tHex")
local xmlValue = require("utils").getValueFromXML
local bimgLib = require("bimg")
local images = require("images")
local sub,len,max,min = string.sub,string.len,math.max,math.min
return function(name)
-- Graphic
local base = Object(name)
local objectType = "Graphic"
local imgData = bimgLib()
local bimgFrame = imgData.getFrameObject(1)
local bimg
local selectedFrame = 1
base:setZIndex(5)
local xOffset, yOffset = 0, 0
local object = {
getType = function(self)
return objectType
end;
setOffset = function(self, _x, _y, rel)
if(rel)then
xOffset = xOffset + _x or 0
yOffset = yOffset + _y or 0
else
xOffset = _x or xOffset
yOffset = _y or yOffset
end
self:updateDraw()
return self
end,
getOffset = function(self)
return xOffset,yOffset
end,
setValuesByXMLData = function(self, data)
base.setValuesByXMLData(self, data)
return self
end,
selectFrame = function(self, id)
if(imgData.getFrameObject(id)==nil)then
imgData.addFrame(id)
end
bimgFrame = imgData.getFrameObject(id)
bimg = bimgFrame.getImage(id)
selectedFrame = id
self:updateDraw()
end,
addFrame = function(self, id)
imgData.addFrame(id)
return self
end,
getFrameMetadata = function(self, id, key)
return imgData.getFrameData(id, key)
end,
setFrameMetadata = function(self, id, key, val)
imgData.setFrameData(id, key, val)
return self
end,
getMetadata = function(self, key)
return imgData.getMetadata(key)
end,
setMetadata = function(self, key, value)
return imgData.setMetadata(key, value)
end,
getFrame = function(self, id)
return imgData.getFrame(id)
end,
getFrameObject = function(self, id)
return imgData.getFrameObject(id)
end,
removeFrame = function(self, id)
imgData.removeFrame(id)
return self
end,
moveFrame = function(self, id, dir)
imgData.moveFrame(id, dir)
return self
end,
getFrames = function(self)
return imgData.getFrames()
end,
getFrameCount = function(self)
return #imgData.getFrames()
end,
getSelectedFrame = function(self)
return selectedFrame
end,
blit = function(self, text, fg, bg, _x, _y)
x = _x or x
y = _y or y
bimgFrame.blit(text, fg, bg, x, y)
bimg = bimgFrame.getImage()
self:updateDraw()
return self
end,
setText = function(self, text, _x, _y)
x = _x or x
y = _y or y
bimgFrame.text(text, x, y)
bimg = bimgFrame.getImage()
self:updateDraw()
return self
end,
setBg = function(self, bg, _x, _y)
x = _x or x
y = _y or y
bimgFrame.bg(bg, x, y)
bimg = bimgFrame.getImage()
self:updateDraw()
return self
end,
setFg = function(self, fg, _x, _y)
x = _x or x
y = _y or y
bimgFrame.fg(fg, x, y)
bimg = bimgFrame.getImage()
self:updateDraw()
return self
end,
getImageSize = function(self)
return imgData.getSize()
end,
setImageSize = function(self, w, h)
imgData.setSize(w, h)
bimg = bimgFrame.getImage()
self:updateDraw()
return self
end,
resizeImage = function(self, w, h)
local newBimg = images.resizeBIMG(imgData.createBimg(), w, h)
imgData = bimgLib(newBimg)
selectedFrame = 1
bimgFrame = imgData.getFrameObject(1)
bimg = bimgFrame.getImage()
self:updateDraw()
return self
end,
loadImage = function(self, path)
if(fs.exists(path))then
local newBimg = images.loadBIMG(path)
imgData = bimgLib(newBimg)
selectedFrame = 1
bimgFrame = imgData.getFrameObject(1)
bimg = bimgFrame.getImage()
self:updateDraw()
end
return self
end,
clear = function(self)
imgData = bimgLib()
bimg = nil
self:updateDraw()
return self
end,
getImage = function(self)
return imgData.createBimg()
end,
draw = function(self)
if (base.draw(self)) then
if (self.parent ~= nil) then
local obx, oby = self:getAnchorPosition()
local w,h = self:getSize()
if(bimg~=nil)then
for k,v in pairs(bimg)do
if(k<=h-yOffset)and(k+yOffset>=1)then
self.parent:blit(obx+xOffset, oby+k-1+yOffset, v[1], v[2], v[3])
end
end
end
end
end
end,
init = function(self)
if(base.init(self))then
self.bgColor = self.parent:getTheme("GraphicBG")
end
end,
}
return setmetatable(object, base)
end

View File

@@ -1,197 +1,158 @@
local Object = require("Object")
local xmlValue = require("utils").getValueFromXML
local images = require("images")
local unpack,sub = table.unpack,string.sub
return function(name)
-- Image
local base = Object(name)
local objectType = "Image"
base:setZIndex(2)
local originalImage
local image
local shrinkedImage
local imageGotShrinked = false
local curFrame = 1
local infinitePlay = false
local animTimer
local usePalette = 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 } }
base.width = 24
base.height = 8
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]
local function getPalette(id)
if(originalImage~=nil)then
local p = {}
for k,v in pairs(colors)do
if(type(v)=="number")then
p[k] = {term.nativePaletteColor(v)}
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
if(originalImage.palette~=nil)then
for k,v in pairs(originalImage.palette)do
p[k] = tonumber(v)
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
if(originalImage[id]~=nil)and(originalImage[id].palette~=nil)then
for k,v in pairs(originalImage[id].palette)do
p[k] = tonumber(v)
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
return p
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 = {
init = function(self)
self.bgColor = self.parent:getTheme("ImageBG")
if(base.init(self))then
self.bgColor = self.parent:getTheme("ImageBG")
end
end,
getType = function(self)
return objectType
end;
loadImage = function(self, path)
image = paintutils.loadImage(path)
imageGotShrinked = false
loadImage = function(self, path, f)
if not(fs.exists(path))then error("No valid path: "..path) end
originalImage = images.loadImageAsBimg(path, f)
curFrame = 1
image = originalImage
if(animTimer~=nil)then
os.cancelTimer(animTimer)
end
self:updateDraw()
return self
end;
shrink = function(self)
shrink()
imageGotShrinked = true
setImage = function(self, data)
originalImage = data
image = originalImage
curFrame = 1
if(animTimer~=nil)then
os.cancelTimer(animTimer)
end
self:updateDraw()
return self
end;
end,
usePalette = function(self, use)
usePalette = use~=nil and use or true
return self
end,
play = function(self, inf)
if(originalImage.animated)then
local t = originalImage[curFrame].duration or originalImage.secondsPerFrame or 0.2
self.parent:addEvent("other_event", self)
animTimer = os.startTimer(t)
infinitePlay = inf or false
end
return self
end,
selectFrame = function(self, fr)
if(originalImage[fr]~=nil)then
curFrame = fr
if(animTimer~=nil)then
os.cancelTimer(animTimer)
end
self:updateDraw()
end
end,
eventHandler = function(self, event, timerId, ...)
base.eventHandler(self, event, timerId, ...)
if(event=="timer")then
if(timerId==animTimer)then
if(originalImage[curFrame+1]~=nil)then
curFrame = curFrame + 1
local t = originalImage[curFrame].duration or originalImage.secondsPerFrame or 0.2
animTimer = os.startTimer(t)
else
if(infinitePlay)then
curFrame = 1
local t = originalImage[curFrame].duration or originalImage.secondsPerFrame or 0.2
animTimer = os.startTimer(t)
end
end
self:updateDraw()
end
end
end,
getMetadata = function(self, key)
return originalImage[key]
end,
getImageSize = function(self)
return originalImage.width, originalImage.height
end,
resizeImage = function(self, w, h)
image = images.resizeBIMG(originalImage, w, h)
self:updateDraw()
return self
end,
setValuesByXMLData = function(self, data)
base.setValuesByXMLData(self, data)
if(xmlValue("shrink", data)~=nil)then if(xmlValue("shrink", data))then self:shrink() end end
if(xmlValue("path", data)~=nil)then self:loadImage(xmlValue("path", data)) end
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()
local w,h = self:getSize()
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, h) do
local line = image[yPos]
for xPos = 1, math.min(#line, w) do
if line[xPos] > 0 then
self.parent:drawBackgroundBox(obx + xPos - 1, oby + yPos - 1, 1, 1, line[xPos])
end
end
end
end
if (image ~= nil) then
if(usePalette)then
self:getBaseFrame():setThemeColor(getPalette(curFrame))
end
local obx, oby = self:getAnchorPosition()
local w,h = self:getSize()
for y,v in ipairs(image[curFrame])do
local t, f, b = unpack(v)
t = sub(t, 1,w)
f = sub(f, 1,w)
b = sub(b, 1,w)
self.parent:blit(obx, oby+y-1, t, f, b)
if(y==h)then break end
end
end
end

View File

@@ -57,9 +57,9 @@ return function(name)
setValue = function(self, val)
base.setValue(self, tostring(val))
if not (internalValueChange) then
textX = tostring(val):len() + 1
wIndex = math.max(1, textX-self:getWidth()+1)
if(self:isFocused())then
textX = tostring(val):len() + 1
wIndex = math.max(1, textX-self:getWidth()+1)
local obx, oby = self:getAnchorPosition()
self.parent:setCursor(true, obx + textX - wIndex, oby+math.floor(self:getHeight()/2), self.fgColor)
end
@@ -202,12 +202,15 @@ return function(name)
if (text:len() < inputLimit or inputLimit <= 0) then
if (inputType == "number") then
local cache = text
if (#text==0 and char == "-") or (char == ".") or (tonumber(char) ~= nil) then
if (textX==1 and char == "-") or (char == ".") or (tonumber(char) ~= nil) then
self:setValue(text:sub(1, textX - 1) .. char .. text:sub(textX, text:len()))
textX = textX + 1
end
if (tonumber(base.getValue()) == nil) then
--self:setValue(cache)
if(char==".")or(char=="-")and(#text>0)then
if (tonumber(base.getValue()) == nil) then
self:setValue(cache)
textX = textX - 1
end
end
end
else
self:setValue(text:sub(1, textX - 1) .. char .. text:sub(textX, text:len()))
@@ -267,44 +270,43 @@ return function(name)
end
end,
eventHandler = function(self, event, paste, p2, p3, p4)
if(base.eventHandler(self, event, paste, p2, p3, p4))then
if(event=="paste")then
if(self:isFocused())then
local text = base.getValue()
local w, h = self:getSize()
internalValueChange = true
if (inputType == "number") then
local cache = text
if (paste == ".") or (tonumber(paste) ~= nil) then
self:setValue(text:sub(1, textX - 1) .. paste .. text:sub(textX, text:len()))
textX = textX + paste:len()
end
if (tonumber(base.getValue()) == nil) then
self:setValue(cache)
end
else
eventHandler = function(self, event, paste, ...)
base.eventHandler(self, event, paste, ...)
if(event=="paste")then
if(self:isFocused())then
local text = base.getValue()
local w, h = self:getSize()
internalValueChange = true
if (inputType == "number") then
local cache = text
if (paste == ".") or (tonumber(paste) ~= nil) then
self:setValue(text:sub(1, textX - 1) .. paste .. text:sub(textX, text:len()))
textX = textX + paste:len()
end
if (textX >= w + wIndex) then
wIndex = (textX+1)-w
if (tonumber(base.getValue()) == nil) then
self:setValue(cache)
end
local obx, oby = self:getAnchorPosition()
local val = tostring(base.getValue())
local cursorX = (textX <= val:len() and textX - 1 or val:len()) - (wIndex - 1)
local x = self:getX()
if (cursorX > x + w - 1) then
cursorX = x + w - 1
end
if (self.parent ~= nil) then
self.parent:setCursor(true, obx + cursorX, oby+math.max(math.ceil(h/2-1, 1)), self.fgColor)
end
self:updateDraw()
internalValueChange = false
else
self:setValue(text:sub(1, textX - 1) .. paste .. text:sub(textX, text:len()))
textX = textX + paste:len()
end
if (textX >= w + wIndex) then
wIndex = (textX+1)-w
end
local obx, oby = self:getAnchorPosition()
local val = tostring(base.getValue())
local cursorX = (textX <= val:len() and textX - 1 or val:len()) - (wIndex - 1)
local x = self:getX()
if (cursorX > x + w - 1) then
cursorX = x + w - 1
end
if (self.parent ~= nil) then
self.parent:setCursor(true, obx + cursorX, oby+math.max(math.ceil(h/2-1, 1)), self.fgColor)
end
self:updateDraw()
internalValueChange = false
end
end
end,

View File

@@ -31,8 +31,9 @@ return function(name)
text = tostring(text)
base:setValue(text)
if (autoSize) then
if(text:len()+self:getX()>self.parent:getWidth())then
local newW = self.parent:getWidth() - self:getX()
local xOffset = self.parent:getOffset()
if(text:len()+self:getX()>self.parent:getWidth()+xOffset)then
local newW = self.parent:getWidth()+xOffset - self:getX()
base.setSize(self, newW, #createText(text, newW))
else
base.setSize(self, text:len(), 1)

View File

@@ -24,8 +24,8 @@ return function(name)
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])
if (#list <= 1) then
self:setValue(list[1], false)
end
self:updateDraw()
return self
@@ -66,7 +66,7 @@ return function(name)
clear = function(self)
list = {}
self:setValue({})
self:setValue({}, false)
self:updateDraw()
return self
end;
@@ -83,7 +83,7 @@ return function(name)
end;
selectItem = function(self, index)
self:setValue(list[index] or {})
self:setValue(list[index] or {}, false)
self:updateDraw()
return self
end;

View File

@@ -68,7 +68,7 @@ return function(name)
clear = function(self)
list = {}
self:setValue({})
self:setValue({}, false)
self:updateDraw()
return self
end;
@@ -142,7 +142,7 @@ return function(name)
end;
selectItem = function(self, index)
self:setValue(list[index] or {})
self:setValue(list[index] or {}, false)
self:updateDraw()
return self
end;

View File

@@ -793,7 +793,7 @@ return function(name, parent)
init = function(self)
if(base.init(self))then
elf.bgColor = self.parent:getTheme("ProgramBG")
self.bgColor = self.parent:getTheme("ProgramBG")
end
end,

View File

@@ -77,7 +77,7 @@ return function(name)
clear = function(self)
list = {}
self:setValue({})
self:setValue({}, false)
self:updateDraw()
return self
end;
@@ -94,7 +94,7 @@ return function(name)
end;
selectItem = function(self, index)
self:setValue(list[index] or {})
self:setValue(list[index] or {}, false)
self:updateDraw()
return self
end;

View File

@@ -1,35 +1,101 @@
local Object = require("Object")
local tHex = require("tHex")
local log = require("basaltLogs")
local xmlValue = require("utils").getValueFromXML
local log = require("basaltLogs")
local rep = string.rep
local rep,find,gmatch,sub,len = string.rep,string.find,string.gmatch,string.sub,string.len
return function(name)
local base = Object(name)
local objectType = "Textfield"
local hIndex, wIndex, textX, textY = 1, 1, 1, 1
local lines = { "" }
local lines = { " " }
local bgLines = { "" }
local fgLines = { "" }
local keyWords = { }
local rules = { }
local startSelX,endSelX,startSelY,endSelY
local selectionBG,selectionFG = colors.lightBlue,colors.black
base.width = 30
base.height = 12
base:setZIndex(5)
local function isSelected()
if(startSelX~=nil)and(endSelX~=nil)and(startSelY~=nil)and(endSelY~=nil)then
return true
end
return false
end
local function getSelectionCoordinates()
local sx,ex,sy,ey
if(isSelected())then
if(startSelX>endSelX)then
sx,ex = endSelX,startSelX
else
sx,ex = startSelX,endSelX
end
if(startSelY>endSelY)then
sy,ey = endSelY,startSelY
else
sy,ey = startSelY,endSelY
end
end
return sx,ex,sy,ey
end
local function getSelection()
end
local function removeSelection(self)
local sx,ex,sy,ey = getSelectionCoordinates(self)
for n=ey,sy,-1 do
if(n==sy)or(n==ey)then
local l = lines[n]
local b = bgLines[n]
local f = fgLines[n]
if(n==sy)and(n==ey)then
l = l:sub(1,sx-1)..l:sub(ex+1,l:len())
b = b:sub(1,sx-1)..b:sub(ex+1,b:len())
f = f:sub(1,sx-1)..f:sub(ex+1,f:len())
elseif(n==sx)then
l = l:sub(1, sx)
b = b:sub(1, sx)
f = f:sub(1, sx)
elseif(n==sy)then
l = l:sub(ex, l:len())
b = b:sub(ex, b:len())
f = f:sub(ex, f:len())
end
lines[n] = l
bgLines[n] = b
fgLines[n] = f
else
table.remove(lines, n)
table.remove(bgLines, n)
table.remove(fgLines, n)
end
end
textX,textY = startSelX,startSelY
startSelX,endSelX,startSelY,endSelY = nil,nil,nil,nil
return self
end
local function stringGetPositions(str, word)
local pos = {}
if(str:len()>0)then
for w in string.gmatch(str, word)do
local s, e = string.find(str, w)
for w in gmatch(str, word)do
local s, e = find(str, w)
if(s~=nil)and(e~=nil)then
table.insert(pos,s)
table.insert(pos,e)
local startL = string.sub(str, 1, (s-1))
local endL = string.sub(str, e+1, str:len())
local startL = sub(str, 1, (s-1))
local endL = sub(str, e+1, str:len())
str = startL..(":"):rep(w:len())..endL
end
end
@@ -150,9 +216,10 @@ return function(name)
end;
clear = function(self)
lines = {""}
lines = {" "}
bgLines = {""}
fgLines = {""}
startSelX,endSelX,startSelY,endSelY = nil,nil,nil,nil
hIndex, wIndex, textX, textY = 1, 1, 1, 1
self:updateDraw()
return self
@@ -227,9 +294,14 @@ return function(name)
end;
removeLine = function(self, index)
table.remove(lines, index or #lines)
if (#lines <= 0) then
table.insert(lines, "")
if(#lines>1)then
table.remove(lines, index or #lines)
table.remove(bgLines, index or #bgLines)
table.remove(fgLines, index or #fgLines)
else
lines = {" "}
bgLines = {""}
fgLines = {""}
end
self:updateDraw()
return self
@@ -311,17 +383,21 @@ return function(name)
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)
table.remove(bgLines, textY + 1)
table.remove(fgLines, textY + 1)
end
if(isSelected())then
removeSelection(self)
else
lines[textY] = lines[textY]:sub(1, textX - 1) .. lines[textY]:sub(textX + 1, lines[textY]:len())
fgLines[textY] = fgLines[textY]:sub(1, textX - 1) .. fgLines[textY]:sub(textX + 1, fgLines[textY]:len())
bgLines[textY] = bgLines[textY]:sub(1, textX - 1) .. bgLines[textY]:sub(textX + 1, bgLines[textY]:len())
if (textX > lines[textY]:len()) then
if (lines[textY + 1] ~= nil) then
lines[textY] = lines[textY] .. lines[textY + 1]
table.remove(lines, textY + 1)
table.remove(bgLines, textY + 1)
table.remove(fgLines, textY + 1)
end
else
lines[textY] = lines[textY]:sub(1, textX - 1) .. lines[textY]:sub(textX + 1, lines[textY]:len())
fgLines[textY] = fgLines[textY]:sub(1, textX - 1) .. fgLines[textY]:sub(textX + 1, fgLines[textY]:len())
bgLines[textY] = bgLines[textY]:sub(1, textX - 1) .. bgLines[textY]:sub(textX + 1, bgLines[textY]:len())
end
end
updateColors(self)
end
@@ -430,9 +506,14 @@ return function(name)
end
end
if not((obx + textX - wIndex >= obx and obx + textX - wIndex < obx + w) and (oby + textY - hIndex >= oby and oby + textY - hIndex < oby + h)) then
wIndex = math.max(1, lines[textY]:len()-w+1)
hIndex = math.max(1, textY - h + 1)
end
local cursorX = (textX <= lines[textY]:len() and textX - 1 or lines[textY]:len()) - (wIndex - 1)
if (cursorX > self.x + w - 1) then
cursorX = self.x + w - 1
if (cursorX > self:getX() + w - 1) then
cursorX = self:getX() + w - 1
end
local cursorY = (textY - hIndex < h and textY - hIndex or textY - hIndex - 1)
if (cursorX < 1) then
@@ -458,14 +539,22 @@ return function(name)
updateColors(self)
self:setValue("")
if not((obx + textX - wIndex >= obx and obx + textX - wIndex < obx + w) and (oby + textY - hIndex >= oby and oby + textY - hIndex < oby + h)) then
wIndex = math.max(1, lines[textY]:len()-w+1)
hIndex = math.max(1, textY - h + 1)
end
local cursorX = (textX <= lines[textY]:len() and textX - 1 or lines[textY]:len()) - (wIndex - 1)
if (cursorX > self.x + w - 1) then
cursorX = self.x + w - 1
if (cursorX > self:getX() + w - 1) then
cursorX = self:getX() + w - 1
end
local cursorY = (textY - hIndex < h and textY - hIndex or textY - hIndex - 1)
if (cursorX < 1) then
cursorX = 0
end
if(isSelected())then
removeSelection(self)
end
self.parent:setCursor(true, obx + cursorX, oby + cursorY, self.fgColor)
self:updateDraw()
return true
@@ -481,18 +570,21 @@ return function(name)
if(anchx+w > anchx + x - (obx+1)+ wIndex)and(anchx < anchx + x - obx+ wIndex)then
textX = x - obx + wIndex
textY = y - oby + hIndex
endSelX = textX
endSelY = textY
if (textX > lines[textY]:len()) then
textX = lines[textY]:len() + 1
endSelX = textX
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
self.parent:setCursor(true, anchx + textX - wIndex, anchy + textY - hIndex, self.fgColor)
self:updateDraw()
end
end
@@ -514,12 +606,10 @@ return function(name)
hIndex = 1
end
if (self.parent ~= nil) then
if (obx + textX - wIndex >= obx and obx + textX - wIndex < obx + w) and (oby + textY - hIndex >= oby and oby + textY - hIndex < oby + h) then
self.parent:setCursor(true, anchx + textX - wIndex, anchy + textY - hIndex, self.fgColor)
else
self.parent:setCursor(false)
end
if (obx + textX - wIndex >= obx and obx + textX - wIndex < obx + w) and (anchy + textY - hIndex >= anchy and anchy + textY - hIndex < anchy + h) then
self.parent:setCursor(true, anchx + textX - wIndex, anchy + textY - hIndex, self.fgColor)
else
self.parent:setCursor(false)
end
self:updateDraw()
return true
@@ -533,8 +623,13 @@ return function(name)
if (lines[y - oby + hIndex] ~= nil) then
textX = x - obx + wIndex
textY = y - oby + hIndex
endSelX = nil
endSelY = nil
startSelX = textX
startSelY = textY
if (textX > lines[textY]:len()) then
textX = lines[textY]:len() + 1
startSelX = textX
end
if (textX < wIndex) then
wIndex = textX - 1
@@ -542,6 +637,7 @@ return function(name)
wIndex = 1
end
end
self:updateDraw()
end
if (self.parent ~= nil) then
self.parent:setCursor(true, anchx + textX - wIndex, anchy + textY - hIndex, self.fgColor)
@@ -550,6 +646,25 @@ return function(name)
end
end,
mouseUpHandler = function(self, button, x, y)
if (base.mouseUpHandler(self, button, x, y)) then
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition())
local anchx, anchy = self:getAnchorPosition()
if (lines[y - oby + hIndex] ~= nil) then
endSelX = x - obx + wIndex
endSelY = y - oby + hIndex
if (endSelX > lines[endSelY]:len()) then
endSelX = lines[endSelY]:len() + 1
end
if(startSelX==endSelX)and(startSelY==endSelY)then
startSelX, endSelX, startSelY, endSelY = nil, nil, nil, nil
end
self:updateDraw()
end
return true
end
end,
eventHandler = function(self, event, paste, p2, p3, p4)
if(base.eventHandler(self, event, paste, p2, p3, p4))then
if(event=="paste")then
@@ -599,9 +714,27 @@ return function(name)
self.parent:setBG(obx, oby + n - 1, bg)
self.parent:setFG(obx, oby + n - 1, fg)
end
if(startSelX~=nil)and(endSelX~=nil)and(startSelY~=nil)and(endSelY~=nil)then
local sx,ex,sy,ey = getSelectionCoordinates(self)
for n=sy,ey do
local line = lines[n]:len()
local xOffset = 0
if(n==sy)and(n==ey)then
xOffset = sx-1
line = line - (sx-1) - (line - ex)
elseif(n==ey)then
line = line - (line - ex)
elseif(n==sy)then
line = line-(sx-1)
xOffset = sx-1
end
self.parent:setBG(obx + xOffset, oby + n - 1, rep(tHex[selectionBG], line))
self.parent:setFG(obx + xOffset, oby + n - 1, rep(tHex[selectionFG], line))
end
end
if(self:isFocused())then
local anchx, anchy = self:getAnchorPosition()
self.parent:setCursor(true, anchx + textX - wIndex, anchy + textY - hIndex, self.fgColor)
--self.parent:setCursor(true, anchx + textX - wIndex, anchy + textY - hIndex, self.fgColor)
end
end
end
@@ -609,6 +742,7 @@ return function(name)
init = function(self)
self.parent:addEvent("mouse_click", self)
self.parent:addEvent("mouse_up", self)
self.parent:addEvent("mouse_scroll", self)
self.parent:addEvent("mouse_drag", self)
self.parent:addEvent("key", self)

View File

@@ -7,6 +7,7 @@ return function(name)
local func
local cRoutine
local isActive = false
local filter
local generateXMLEventFunction = function(self, str)
if(str:sub(1,1)=="#")then
@@ -53,12 +54,21 @@ return function(name)
func = f
cRoutine = coroutine.create(func)
isActive = true
filter=nil
local ok, result = coroutine.resume(cRoutine)
filter = result
if not (ok) then
if (result ~= "Terminated") then
error("Thread Error Occurred - " .. result)
end
end
self.parent:addEvent("mouse_click", self)
self.parent:addEvent("mouse_up", self)
self.parent:addEvent("mouse_scroll", self)
self.parent:addEvent("mouse_drag", self)
self.parent:addEvent("key", self)
self.parent:addEvent("key_up", self)
self.parent:addEvent("char", self)
self.parent:addEvent("other_event", self)
return self
end;
@@ -72,21 +82,58 @@ return function(name)
stop = function(self, f)
isActive = false
self.parent:removeEvent("mouse_click", self)
self.parent:removeEvent("mouse_up", self)
self.parent:removeEvent("mouse_scroll", self)
self.parent:removeEvent("mouse_drag", self)
self.parent:removeEvent("key", self)
self.parent:removeEvent("key_up", self)
self.parent:removeEvent("char", self)
self.parent:removeEvent("other_event", self)
return self
end;
eventHandler = function(self, event, p1, p2, p3)
mouseHandler = function(self, ...)
self:eventHandler("mouse_click", ...)
end,
mouseUpHandler = function(self, ...)
self:eventHandler("mouse_up", ...)
end,
mouseScrollHandler = function(self, ...)
self:eventHandler("mouse_scroll", ...)
end,
mouseDragHandler = function(self, ...)
self:eventHandler("mouse_drag", ...)
end,
mouseMoveHandler = function(self, ...)
self:eventHandler("mouse_move", ...)
end,
keyHandler = function(self, ...)
self:eventHandler("key", ...)
end,
keyUpHandler = function(self, ...)
self:eventHandler("key_up", ...)
end,
charHandler = function(self, ...)
self:eventHandler("char", ...)
end,
eventHandler = function(self, event, ...)
if (isActive) then
if (coroutine.status(cRoutine) ~= "dead") then
local ok, result = coroutine.resume(cRoutine, event, p1, p2, p3)
if (coroutine.status(cRoutine) == "suspended") then
if(filter~=nil)then
if(event~=filter)then return end
filter=nil
end
local ok, result = coroutine.resume(cRoutine, event, ...)
filter = result
if not (ok) then
if (result ~= "Terminated") then
error("Thread Error Occurred - " .. result)
end
end
else
isActive = false
self:stop()
end
end
end;

View File

@@ -40,6 +40,8 @@ return { -- The default main theme for basalt!
SwitchInactive = colors.red,
SwitchActive = colors.green,
LabelBG = false,
LabelText = colors.black
LabelText = colors.black,
GraphBG = colors.gray,
GraphText = colors.black
}

View File

@@ -1,4 +1,4 @@
# Welcome to The Basalt Wiki!
# Welcome to The Basalt Wiki
*Note: The Basalt Wiki is a work in progress. Please treat wiki errors the same as bugs and report them accordingly.*
@@ -6,7 +6,7 @@ Here you can find information about how to use Basalt as well as examples of fun
## About Basalt
Basalt is intended to be an easy-to-understand UI Framework designed for CC:Tweaked (Also know as "ComputerCraft: Tweaked") - a popular minecraft mod. For more information about CC:Tweaked, checkout the project's [wiki](https://tweaked.cc/) or [download](https://modrinth.com/mod/cc-tweaked).
Basalt is intended to be an easy-to-understand UI Framework designed for CC:Tweaked (Also known as "ComputerCraft: Tweaked") - a popular minecraft mod. For more information about CC:Tweaked, checkout the project's [wiki](https://tweaked.cc/) or [download](https://modrinth.com/mod/cc-tweaked).
## Quick Demo

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 717 B

Binary file not shown.

Binary file not shown.

View File

@@ -1,4 +1,4 @@
- Getting Started
- [Home](Home)
- [Quick Start](home/Quick-Start)
- [Installer](home/installer)
- [How To](home/How-To)
- [Download](home/download)

View File

@@ -1,7 +1,7 @@
- About
- [Home](Home.md)
- [Quick Start](home/Quick-Start.md)
- [Installer](home/installer)
- [Home](home)
- [How To](home/How-To)
- [Download](home/download)
- Objects
- [Basalt](objects/Basalt.md)
- [Object](objects/Object.md)

59
docs/home/How-To.md Normal file
View File

@@ -0,0 +1,59 @@
After downloading the project you can finally start creating your own program and use basalt. The first thing you want to use in your program is always:
```lua
local basalt = require("basalt")
```
It doesn't matter if you're using the source folder or the minified/packed version of basalt. Both can be found by using require("basalt") without .lua.
Also to really run basalt you should use
```lua
basalt.autoUpdate()
```
somewhere on the bottom of your program. basalt.autoUpdate() starts the event listener and the draw handler.
## Example
Here is a fully working example of how a program could look like:
```lua
local basalt = require("basalt") --> Load the basalt framework into the variable called "basalt"
--> Now we want to create a base frame, we call the variable "main" - by default everything you create is visible. (you don't need to use :show())
local main = basalt.createFrame()
local button = mainFrame:addButton() --> Here we add our first button
button:setPosition(4, 4) -- of course we want to change the default position of our button
button:setSize(16, 3) -- and the default size.
button:setText("Click me!") --> This method displays what the text of our button should look like
local function buttonClick() --> Let us create a function we want to call when the button gets clicked
basalt.debug("I got clicked!")
end
-- Now we just need to register the function to the buttons onClick event handlers, this is how we can achieve that:
button:onClick(buttonClick)
basalt.autoUpdate() -- As soon as we call basalt.autoUpdate, the event and draw handlers will listen to any incomming events (and draw if necessary)
```
If you're like us and strive for succinct and beautiful code, here is a cleaner implementation of the code above:
```lua
local basalt = require("basalt")
local main = basalt.createFrame()
local button = main --> Basalt returns an instance of the object on most methods, to make use of "call-chaining"
:addButton() --> This is an example of call chaining
:setPosition(4,4)
:setText("Click me!")
:onClick(
function()
basalt.debug("I got clicked!")
end)
basalt.autoUpdate()
```

View File

@@ -1,95 +0,0 @@
# Quick Start
## How to use
To load Basalt into your project, make use of the following code on top of your code.
```lua
local basalt = require("basalt")
```
It does not matter if you have installed the single file version or the full folder project.
Both versions can be loaded by using `require("Basalt")`, you dont need to add `.lua`.
## Download
### Download the folder version
This version is for people who'd like to work with Basalt, change something in Basalt, or checkout the project.
But you are also able to just use it to create your own UI.
To install the full project to your CC:Tweaked Computer, use the following command on your CC:Tweaked shell:
`pastebin run ESs1mg7P`
This will download the project as a folder called "Basalt". You are immediatly after the download is done able to use it in your projects.
### Download the single file version
This is the version you should use if you're done with programming. It is a little bit faster and it is also minified, which makes the project smaller.
To install the single filed project to your CC:Tweaked Computer, use the following command on your CC:Tweaked shell:
`pastebin run ESs1mg7P packed`
This will download the project as a single file called "basalt.lua". You are immediatly after the download is done able to use it in your projects.
### Basalt Package Manager
**The Basalt Package Manager is still in alpha!**
The Basalt Package Manager is a visual installer, you are able to change some settings, also to choose which objects are necessary for your projects and which are not.
To install the BPM (Basalt Package Manager) use the following command on your CC:Tweaked shell:
`pastebin run ESs1mg7P bpm true`
The true keyword in the end is optional and would simply start BPM immediately.
## Example
Here is a fully functioning example of Basalt code
```lua
local basalt = require("basalt") --> Load the Basalt framework
--> Create the first frame. Please note that Basalt needs at least one active "non-parent" frame to properly supply events
--> When Basalt#createFrame makes use of unique identifiers (commonly referred to as UIDs), meaning that the supplied value must be UNIQUE
local mainFrame = basalt.createFrame("mainFrame")
--> Show the frame to the user
mainFrame:show()
local button = mainFrame:addButton("clickableButton") --> Add a button to the mainFrame (With a unique identifier)
--> Set the position of the button, Button#setPosition follows an x, y pattern.
--> The x value is how far right the object should be from its anchor (negative values from an anchor will travel left)
--> The y value is how far down the object should be from its anchor (negative values from an anchor will travel up)
button:setPosition(4, 4)
button:setText("Click me!") --> Set the text of our button
local function buttonClick() --> This function serves as our click logic
basalt.debug("I got clicked!")
end
--> Remember! You cannot supply buttonClick(), that will only supply the result of the function
--> Make sure the button knows which function to call when it's clicked
button:onClick(buttonClick)
button:show() --> Make the button visible, so the user can click it
basalt.autoUpdate() --> Basalt#autoUpdate starts the event listener to detect user input
```
If you're like us and strive for succinct and beautiful code, here is a cleaner implementation of the code above:
```lua
local basalt = require("basalt")
local mainFrame = basalt.createFrame("mainFrame"):show()
local button = mainFrame --> Basalt returns an instance of the object on most methods, to make use of "call-chaining"
:addButton("clickableButton") --> This is an example of call chaining
:setPosition(4,4)
:setText("Click me!")
:onClick(
function()
basalt.debug("I got clicked!")
end)
:show()
basalt.autoUpdate()
```

36
docs/home/download.md Normal file
View File

@@ -0,0 +1,36 @@
Basalt provides multiple unique versions. A source version, a minified version and a web version.
## Source
This version is, like the name already says, the source code of basalt. If you want to dig into the code, add additional content or just prefer to use the source, then you should aim for the source-version.
The following command allows you to download the source-version on your computer:
`wget run https://basalt.madefor.cc/install.lua source [foldername] [branch]`
The first optional argument is the folder name you wish that basalt should be installed into, by default the folder is called basalt.
The second optional argument is the branch you want to use. If you don't know what this means please ignore it (the 2 options are master and dev)
## Minified / Packed
This version is the minified version, i also call it the packed version. There are 2 changes, the first one is that the code will be shown minified which makes the size much smaller, the second change is that you will recieve a file instead of a folder.
The following command allows you to download the packed-version on your computer:
`wget run https://basalt.madefor.cc/install.lua packed [filename] [branch]`
The first optional argument is the file name you wish that the installer should use, by default the file is called basalt.lua.
The second optional argument is the branch you want to use. If you don't know what this means please ignore it (the 2 options are master and dev)
## Web
The web version is a special version, used if your goal is to keep your project's size as small as possible. I suggest you to use the web version only if you don't restart your program over and over again. For example if you designed your program to reboot after the user made a bad choice (leads into a error or something like that) it is better to use the minified/source version.
The following command allows you to download the web-version on your computer:
`wget run https://basalt.madefor.cc/install.lua web [version] [filename]`
By default the first argument is the latest version of basalt's releases. [Here](https://github.com/Pyroxenium/Basalt/tree/master/docs/versions) you can see which versions are available to use.
For example: wget run https://basalt.madefor.cc/install.lua web basalt-1.6.3.lua - the second argument is just the file name, default is basaltWeb.lua.
Remember to rename `local basalt = require("basalt")` into `local basalt = require("basaltWeb")` if you want to use the web-version

View File

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

View File

@@ -33,6 +33,7 @@
</head>
<body>
<div id="app">Did you know: Basalt is a Pyroxene?></div>
<script src="//cdn.jsdelivr.net/npm/docsify-edit-on-github"></script>
<script>
window.$docsify = {
logo: '/_media/logo.png',
@@ -44,7 +45,19 @@
homepage: 'Home.md',
name: 'Basalt',
repo: 'https://github.com/Pyroxenium/Basalt',
auto2top: true
auto2top: true,
search: {
maxAge: 86400000, // Expiration time, the default one day
paths: 'auto',
placeholder: 'Type to search',
noData: 'No Results!',
// Headline depth, 1 - 6
depth: 2,
hideOtherSidebarContent: false, // whether or not to hide other sidebar content
},
plugins: [
EditOnGithubPlugin.create("https://github.com/Pyroxenium/Basalt/blob/master/docs/", null, "Edit on Github")
]
}
</script>
<!-- Docsify v4 -->
@@ -52,6 +65,8 @@
<script src="https://cdn.jsdelivr.net/npm/docsify-themeable@0/dist/js/docsify-themeable.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/prismjs@1.28.0/components/prism-lua.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/@alertbox/docsify-footer/dist/docsify-footer.min.js"></script>
<script src="//unpkg.com/docsify/lib/plugins/search.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/docsify-copy-code/dist/docsify-copy-code.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/docsify/lib/plugins/zoom-image.min.js"></script>
</body>
</html>

View File

@@ -4,14 +4,52 @@ local args = table.pack(...)
local installer = {printStatus=true}
installer.githubPath = "https://raw.githubusercontent.com/Pyroxenium/Basalt/"
local function printStatus(...)
if(installer.printStatus)then
print(...)
elseif(type(installer.printStatus)=="function")then
installer.printStatus(...)
end
end
function installer.get(url)
local httpReq = http.get(url, _G._GIT_API_KEY and {Authorization = "token ".._G._GIT_API_KEY})
printStatus("Downloading "..url)
if(httpReq~=nil)then
local content = httpReq.readAll()
if not content then
error("Could not connect to website")
end
return content
end
end
local basaltDataCache
function installer.getBasaltData()
if(basaltDataCache~=nil)then return basaltDataCache end
local content
printStatus("Downloading basalt data...")
if(fs.exists("basaltdata.json"))then
content = fs.open("basaltdata.json", "r")
else
content = installer.get("https://basalt.madefor.cc/basaltdata.json")
end
if(content~=nil)then
content = content.readAll()
basaltDataCache = textutils.unserializeJSON(content)
printStatus("Successfully downloaded basalt data!")
return basaltDataCache
end
end
-- Creates a filetree based on my github project, ofc you can use this in your projects if you'd like to
function installer.createTableTree(page, branch, dirName)
function installer.createTree(page, branch, dirName)
dirName = dirName or ""
if(installer.printStatus)then print("Receiving file tree for "..dirName) end
printStatus("Receiving file tree for "..(dirName~="" and "Basalt/"..dirName or "Basalt"))
local tree = {}
local request = http.get(page, _G._GIT_API_KEY and {Authorization = "token ".._G._GIT_API_KEY})
if not(page)then return end
if(request==nil)then error("API rate limit exceeded. It will be available again in a couple of hours.") end
if(request==nil)then error("API rate limit exceeded. It will be available again in one hour.") end
for _,v in pairs(textutils.unserialiseJSON(request.readAll()).tree)do
if(v.type=="blob")then
table.insert(tree, {name = v.path, path=fs.combine(dirName, v.path), url=installer.githubPath..branch.."/Basalt/"..fs.combine(dirName, v.path), size=v.size})
@@ -22,24 +60,23 @@ function installer.createTableTree(page, branch, dirName)
return tree
end
function installer.createTree(page, branch, dirName)
function installer.createTreeByBasaltData(page, branch, dirName)
dirName = dirName or ""
if(installer.printStatus)then print("Receiving file tree for "..dirName) end
local tree = {}
local request = http.get(page, _G._GIT_API_KEY and {Authorization = "token ".._G._GIT_API_KEY})
if not(page)then return end
if(request==nil)then error("API rate limit exceeded. It will be available again in a couple of hours.") end
for _,v in pairs(textutils.unserialiseJSON(request.readAll()).tree)do
if(v.type=="blob")then
table.insert(tree, {name = v.path, path=fs.combine(dirName, v.path), url=installer.githubPath..branch.."/Basalt/"..fs.combine(dirName, v.path), size=v.size})
elseif(v.type=="tree")then
for k,v in pairs(installer.createTree(v.url, branch, fs.combine(dirName, v.path)))do
table.insert(tree, v)
printStatus("Receiving file tree for "..(dirName~="" and "Basalt/"..dirName or "Basalt"))
local bData = installer.getBasaltData()
if(bData~=nil)then
local tree = {}
for k,v in pairs(bData.structure)do
if(k=="base")then
for a,b in pairs(v)do
table.insert(tree, b)
end
else
tree[k] = v
end
end
return tree
end
return tree
end
local function splitString(str, sep)
@@ -53,18 +90,6 @@ local function splitString(str, sep)
return t
end
function installer.get(url)
local httpReq = http.get(url, _G._GIT_API_KEY and {Authorization = "token ".._G._GIT_API_KEY})
if(installer.printStatus)then print("Downloading "..url) end
if(httpReq~=nil)then
local content = httpReq.readAll()
if not content then
error("Could not connect to website")
end
return content
end
end
function installer.createIgnoreList(str)
local files = splitString(str, ":")
local ignList = {}
@@ -88,14 +113,35 @@ function installer.download(url, file)
end
end
function installer.getRelease(version)
local v = installer.getBasaltData().versions[version]
if(v~=nil)then
printStatus("Downloading basalt "..version)
local content = http.get("https://basalt.madefor.cc/versions/"..v, {Authorization = _G._GIT_API_KEY and "token ".._G._GIT_API_KEY})
if(content~=nil)then
return content.readAll()
end
end
end
function installer.downloadRelease(version, file)
local content = installer.getRelease(version)
if(content~=nil)then
local f = fs.open(file or "basalt.lua", "w")
f.write(content)
f.close()
return true
end
return false
end
function installer.getPackedProject(branch, ignoreList)
installer.printStatus = false
if (ignoreList==nil)then
ignoreList = {"init.lua"}
else
table.insert(ignoreList, "init.lua")
end
local projTree = installer.createTableTree("https://api.github.com/repos/Pyroxenium/Basalt/git/trees/"..branch..":Basalt", branch, "")
local projTree = installer.createTree("https://api.github.com/repos/Pyroxenium/Basalt/git/trees/"..branch..":Basalt", branch, "")
local filteredList = {}
local project = {}
@@ -190,6 +236,33 @@ end
return projectContent
end
function installer.generateWebVersion(file, version)
if(fs.exists(file))then error("A file called "..file.." already exists!") end
version = version or "latest.lua"
local request = http.get("https://basalt.madefor.cc/versions/"..version, _G._GIT_API_KEY and {Authorization = "token ".._G._GIT_API_KEY})
if(request~=nil)then
if(fs.exists(file))then
fs.delete(file)
local f = fs.open(file, "w")
local link = "https://basalt.madefor.cc/versions/"..version
local content = 'local request = http.get("'..link..'", _G._GIT_API_KEY and {Authorization = "token ".._G._GIT_API_KEY})\n'
content = content..
[[
if(request~=nil)then
return load(request.readAll())()
else
error("Unable to connect to ]]..link..[[")
end
]]
f.write(content)
f.close()
printStatus("Web version successfully downloaded!")
end
else
error("Version doesn't exist!")
end
end
function installer.getProjectFiles(branch, ignoreList)
local projTree = installer.createTree("https://api.github.com/repos/Pyroxenium/Basalt/git/trees/"..branch..":Basalt", branch, "")
local filteredList = {}
@@ -207,8 +280,18 @@ function installer.getProjectFiles(branch, ignoreList)
end
for k,v in pairs(projTree)do
if not(isInIgnoreList(v))then
table.insert(filteredList, v)
if not(isInIgnoreList(v.name))then
if(type(k)=="string")then
local sub = {}
for a,b in pairs(v)do
if not(isInIgnoreList(b.name))then
table.insert(sub, b)
end
end
filteredList[k] = sub
else
table.insert(filteredList, v)
end
end
end
@@ -219,7 +302,15 @@ function installer.getProjectFiles(branch, ignoreList)
local fList = {}
local delay = 0
for k,v in pairs(filteredList)do
table.insert(fList, function() sleep(delay) downloadFile(v.url, v.path) delay = delay + 0.05 end)
if(type(k)=="string")then
for a,b in pairs(v)do
table.insert(fList, function() sleep(delay) downloadFile(b.url, b.path) end)
delay = delay + 0.05
end
else
table.insert(fList, function() sleep(delay) downloadFile(v.url, v.path) end)
delay = delay + 0.05
end
end
parallel.waitForAll(table.unpack(fList))
@@ -227,6 +318,7 @@ function installer.getProjectFiles(branch, ignoreList)
end
function installer.downloadPacked(filename, branch, ignoreList, minify)
if(fs.exists(filename))then error("A file called "..filename.." already exists!") end
local projectContent = installer.getPackedProject(branch, ignoreList)
if(minify)then
local min
@@ -246,38 +338,22 @@ function installer.downloadPacked(filename, branch, ignoreList, minify)
end
local f = fs.open(filename, "w")
f.write(projectContent)
f.close()
f.close()
printStatus("Packed version successfully downloaded!")
end
function installer.downloadProject(projectDir, branch, ignoreList)
local projectFiles = installer.getProjectFiles(branch, ignoreList)
if(fs.exists(projectDir))then error("A folder called "..projectDir.." already exists!") end
projectDir = projectDir or "basalt"
branch = branch or "master"
local function downloadFile(url, path)
print("Downloading "..path)
local files = splitString(path)
if(#files>1)then
local folderPath = ""
for a,b in pairs(files)do
if(a<#files)then
folderPath = fs.combine(folderPath, b)
else
if not (fs.exists(folderPath))then fs.makeDir(folderPath) end
installer.download(url, fs.combine(projectDir, path))
end
end
else
installer.download(url, fs.combine(projectDir, path))
end
end
local fList = {}
local delay = 0
local projectFiles = installer.getProjectFiles(branch, ignoreList)
fs.makeDir(projectDir)
for k,v in pairs(projectFiles)do
table.insert(fList, function() sleep(delay) downloadFile(v.url, v.path) delay = delay + 0.05 end)
local f = fs.open(fs.combine(projectDir, k), "w")
f.write(v)
f.close()
end
parallel.waitForAll(table.unpack(fList))
printStatus("Source version successfully downloaded!")
end
if(#args>0)then
@@ -289,6 +365,10 @@ if(#args>0)then
installer.downloadPacked(args[2] or "basalt.lua", args[3] or "master", args[4]~=nil and installer.createIgnoreList(args[4]) or nil, args[5] == "false" and false or true)
elseif(string.lower(args[1])=="source")then
installer.downloadProject(args[2] or "basalt", args[3] or "master", args[4]~=nil and installer.createIgnoreList(args[4]) or nil)
elseif(string.lower(args[1])=="web")then
installer.generateWebVersion(args[3] or "basaltWeb.lua", args[2] or "latest.lua")
elseif(string.lower(args[1])=="file")then
installer.download("https://basalt.madefor.cc/versions/"..args[2] or "latest.lua", args[3] or "basalt.lua")
end
end

View File

@@ -1,4 +1,12 @@
With animations, you can create a beautiful experience for users while interacting with your program.<br>
With animations, you can create a beautiful experience for users while interacting with your program.
There are 2 types of animations, predefined animations and custom animations. By using add and wait you can create custom
animations (calls). Pre-defined methods are for example move, offset, size, changeText,...
:setObject always sets the object on what pre-defined methods should apply on.
When calling a pre-defined animation it will check what is safed as object (:setObject) and will calculate the animation methods based on that which means you won't
be able to change the object on the fly - you will always have to recreate the animation itself
| | |
|---|---|
@@ -6,6 +14,8 @@ With animations, you can create a beautiful experience for users while interacti
|[wait](objects/Animation/wait.md)|Adds a amount to the animation time
|[play](objects/Animation/play.md)|Plays the animation
|[cancel](objects/Animation/cancel.md)|Cancels the animation
|[addMode](objects/Animation/addMode.md)|Adds custom easings
|[setMode](objects/Animation/setMode.md)|Changes the current easing-calculation
|[setObject](objects/Animation/setObject.md)|Sets an object on which predefined animations should work on
|[move](objects/Animation/move.md)|Predefined animation: moves the object to a new position
|[offset](objects/Animation/offset.md)|Predefined animation: Changes the offset of that object
@@ -18,4 +28,5 @@ With animations, you can create a beautiful experience for users while interacti
| | |
|---|---|
|[onStart](objects/Animation/onStart.md)|Gets called as soon as the animation is started
|[onDone](objects/Animation/onDone.md)|Gets called as soon as the animation has finished

View File

@@ -0,0 +1,30 @@
## addMode
Adds a new easing curve into the available easing list. Checkout the animation object if you want to know how this works.
#### Parameters:
1. `string` - The name of the curve you want to use.
2. `functon` - The function to call
#### Returns:
1. `animation` Animation in use
#### Usage:
* Creates a new curve
```lua
local mainFrame = basalt.createFrame()
local testButton = mainFrame:addButton("buttonToAnimate")
local aAnimation = mainFrame:addAnimation():setObject(testButton)
local function easeInBack(t) -- t is the time from 0 to 1
local c1 = 1.70158;
local c3 = c1 + 1
return c3*t^3-c1*t^2
end
aAnimation:addMode("coolEaseInBack", easeInBack)
aAnimation:setMode("coolEaseInBack"):move(15,3,2):play()
```

View File

@@ -0,0 +1,16 @@
## onStart
`onStart(self)`<br>
This is a event which gets fired as soon as the animation is started.
```lua
local basalt = require("Basalt")
local mainFrame = basalt.createFrame()
local testButton = mainFrame:addButton("buttonToAnimate")
local aAnimation = mainFrame:addAnimation():setObject(testButton):changeTextColor({colors.red, colors.yellow, colors.green}, 2)
aAnimation:onStart(function()
basalt.debug("The animation is started")
end)
aAnimation:play()
```

View File

@@ -0,0 +1,36 @@
## setMode
Changes the easing curve. If you want to test them, here is a interesting website: https://easings.co
#### Parameters:
1. `string` - The name of the curve you want to use.
#### Returns:
1. `animation` Animation in use
#### Usage:
* Takes 2 seconds to move the object from its current position to x15 y3
```lua
local mainFrame = basalt.createFrame()
local testButton = mainFrame:addButton("buttonToAnimate")
local aAnimation = mainFrame:addAnimation():setObject(testButton):setMode("easeInBounce"):move(15,3,2):play()
```
## Easing Curve List
Here is a list of all available easing curves:
| | | |
|---|---|---|
|linear||
|easIn|easeOut|easeInOut
|easeInSine|easeOutSine|easeInOutSine
|easeInBack|easeOutBack|easeInOutBack
|easeInCubic|easeOutCubic|easeInOutCubic
|easeInElastic|easeOutElastic|easeInOutElastic
|easeInExpo|easeOutExpo|easeInOutExpo
|easeInBack|easeOutBack|easeInOutBack
|easeInQuad|easeOutQuad|easeInOutQuad
|easeInQuint|easeOutQuint|easeInOutQuint
|easeInQuart|easeOutQuart|easeInOutQuart
|easeInCirc|easeOutCirc|easeInOutCirc
|easeInBounce|easeOutBounce|easeInOutBounce

View File

@@ -27,6 +27,8 @@ You are now able to access the following list of methods:
|[schedule](objects/Basalt/schedule.md)|Schedules a new task
|[setActiveFrame](objects/Basalt/setActiveFrame.md)|Sets the active frame
|[setTheme](objects/Basalt/setTheme.md)|Changes the base theme of basalt
|[setMouseDragThrottle](objects/Basalt/setMouseDragThrottle.md)|Changes the mouse drag throttle amount
|[setMouseMoveThrottle](objects/Basalt/setMouseMoveThrottle.md)|CraftOS-PC: Changes the mouse move throttle amount
|[setVariable](objects/Basalt/setVariable.md)|Sets a variable which you can access via XML
|[stopUpdate / stop](objects/Basalt/stopUpdate.md)|Stops the currently active event and draw listener
|[update](objects/Basalt/update.md)|Starts the event and draw listener once

View File

@@ -0,0 +1,18 @@
# Basalt
## setMouseDragThrottle
Changes the drag throttle of all drag events. Default value is 50ms - which is 0.05s.
Instead of sending all mouse_drag events to the :onDrag handlers basalt sends every 0.05s (while dragging) the most recent drag event to all
drag handlers. If you need all drag events - just change the value to 0.
### Parameters
1. `number` A number in miliseconds.
### Usage
```lua
local basalt = require("basalt")
basalt.setMouseDragThrottle(0)
```

View File

@@ -0,0 +1,20 @@
# Basalt
## setMouseMoveThrottle
This feature is only available for [CraftOS-PC](https://www.craftos-pc.cc).
CraftOS-PC has a builtin mouse_move event, which is disabled by default. By using this method it will also enable the event for you. Remember - basalt does not disable the event after closing the program, which means the event stays active. If you want to disable the event please use config.set("mouse_move_throttle", -1) in your lua prompt or your program.
Sidenote: a very low amount can make the program laggy - because it litterally spams the mouse_move event. So use it carefully.
### Parameters
1. `number` A number in miliseconds.
### Usage
```lua
local basalt = require("basalt")
basalt.setMouseMoveThrottle(50)
```

View File

@@ -28,6 +28,7 @@ some special functionality to create very advanced programs.
|[setScrollAmount](objects/Frame/setScrollAmount.md)|Sets how far the user is allowed to scroll
This is how you would implement frames via xml:
```xml
<frame>
<frame width="parent.w * 0.5" bg="red">
@@ -37,4 +38,297 @@ This is how you would implement frames via xml:
<textfield bg="green" x="2" width="parent.w-2" />
</frame>
</frame>
```
```
## Examples
Here are some examples on how you can use frames to create very advanced programs. Because of the screen size limitation of CC:Tweaked frames can become very useful in almost every scenario. You will find some examples here on how you could implement them.
### Menubar for switching frames
This is a example on how you can create a menubar which switches your frames (without animation).
<details>
<summary>Click here to show code</summary>
```lua
local basalt = require("basalt") -- we need basalt here
local main = basalt.createFrame():setTheme({FrameBG = colors.lightGray, FrameFG = colors.black}) -- we change the default bg and fg color for frames
local sub = { -- here we create a table where we gonna add some frames
main:addFrame():setPosition(1, 2):setSize("parent.w", "parent.h - 1"), -- obviously the first one should be shown on program start
main:addFrame():setPosition(1, 2):setSize("parent.w", "parent.h - 1"):hide(),
main:addFrame():setPosition(1, 2):setSize("parent.w", "parent.h - 1"):hide(),
}
local function openSubFrame(id) -- we create a function which switches the frame for us
if(sub[id]~=nil)then
for k,v in pairs(sub)do
v:hide()
end
sub[id]:show()
end
end
local menubar = main:addMenubar():setScrollable() -- we create a menubar in our main frame.
:setSize("parent.w")
:onChange(function(self, val)
openSubFrame(self:getItemIndex()) -- here we open the sub frame based on the table index
end)
:addItem("Example 1")
:addItem("Example 2")
:addItem("Example 3")
-- Now we can change our sub frames, if you want to access a sub frame just use sub[subid], some examples:
sub[1]:addButton():setPosition(2, 2)
sub[2]:addLabel():setText("Hello World!"):setPosition(2, 2)
sub[3]:addLabel():setText("Now we're on example 3!"):setPosition(2, 2)
sub[3]:addButton():setText("No functionality"):setPosition(2, 4):setSize(18, 3)
basalt.autoUpdate()
```
</details>
<br>
<video width="600" controls autoplay loop muted>
<source src="./_media/frames-with-menubars.mp4" type="video/mp4">
</video>
### Sidebar with buttons to switch frames
Here we will find out how to create a sidebar (which are also just frames) - the sidebar should have buttons to opens the frames for us.
<details>
<summary>Click here to show code</summary>
```lua
local basalt = require("basalt") -- we need basalt here
local main = basalt.createFrame():setTheme({FrameBG = colors.lightGray, FrameFG = colors.black})
--[[
Here we create the sidebar, on focus it should change the position to parent.w - (self.w-1) which "opens the frame"
when the focus gets lost we simply change the position to "parent.w"
As you can see we add :setZIndex(25) - this makes sure the sidebar frame is always more important than our normal sub frames.
:setScrollable just makes the sidebar frame scrollable (in case you're adding more frames)
]]
local sidebar = main:addFrame():setBackground(colors.gray):setPosition("parent.w", 1):setSize(15, "parent.h"):setZIndex(25):setScrollable()
:onGetFocus(function(self)
self:setPosition("parent.w - (self.w-1)")
end)
:onLoseFocus(function(self)
self:setPosition("parent.w")
end)
-- Once again we add 3 frames, the first one should be immediatly visible
local sub = {
main:addFrame():setPosition(1, 1):setSize("parent.w", "parent.h"),
main:addFrame():setPosition(1, 1):setSize("parent.w", "parent.h"):hide(),
main:addFrame():setPosition(1, 1):setSize("parent.w", "parent.h"):hide(),
}
--This part of the code adds buttons based on the sub table.
local y = 2
for k,v in pairs(sub)do
sidebar:addButton():setText("Example "..k) -- creating the button and adding a name k is just the index
:setBackground(colors.black)
:setForeground(colors.lightGray)
:setSize("parent.w - 2", 3)
:setPosition(2, y)
:onClick(function() -- here we create a on click event which hides ALL sub frames and then shows the one which is linked to the button
for a, b in pairs(sub)do
b:hide()
v:show()
end
end)
y = y + 4
end
sub[1]:addButton():setPosition(2, 2)
sub[2]:addLabel():setText("Hello World!"):setPosition(2, 2)
sub[3]:addLabel():setText("Now we're on example 3!"):setPosition(2, 2)
sub[3]:addButton():setText("No functionality"):setPosition(2, 4):setSize(18, 3)
basalt.autoUpdate()
```
</details>
<br>
<video width="600" controls autoplay loop muted>
<source src="./_media/frames-with-sidebar.mp4" type="video/mp4">
</video>
### Movable frames with a program object
In this example you will see how you can add movable frames with a program object in it. It also shows you how you dynamically add new frames.
<details>
<summary>Click here to show code</summary>
```lua
local basalt = require("basalt")
local main = basalt.createFrame():setTheme({FrameBG = colors.lightGray, FrameFG = colors.black})
local id = 1
local processes = {}
local function openProgram(path, title, x, y, w, h)
local pId = id
id = id + 1
local f = main:addFrame()
:setMovable()
:setSize(w or 30, h or 12)
:setPosition(x or math.random(2, 12), y or math.random(2, 8))
f:addLabel()
:setSize("parent.w", 1)
:setBackground(colors.black)
:setForeground(colors.lightGray)
:setText(title or "New Program")
f:addProgram()
:setSize("parent.w", "parent.h - 1")
:setPosition(1, 2)
:execute(path or "rom/programs/shell.lua")
f:addButton()
:setSize(1, 1)
:setText("X")
:setBackground(colors.black)
:setForeground(colors.red)
:setPosition("parent.w", 1)
:onClick(function()
f:remove()
processes[pId] = nil
end)
processes[pId] = f
return f
end
openProgram("rom/programs/fun/worm.lua")
main:addButton():setPosition("parent.w - 16", 2):setText("Open"):onClick(function()
openProgram()
end)
basalt.autoUpdate()
```
</details>
<br>
<video width="600" controls autoplay loop muted>
<source src="./_media/dynamic-frames.mp4" type="video/mp4">
</video>
### Resizable frames
If you want to make your frames resizeable, there is no way offered by basalt - so you would have to do it yourself. However such a implementation is very simple as you can see here.
<details>
<summary>Click here to show code</summary>
```lua
local basalt = require("basalt")
local main = basalt.createFrame():setTheme({FrameBG = colors.black, FrameFG = colors.lightGray})
local sub = main:addFrame():setSize(25, 12):setPosition(3, 3)
local function makeResizeable(frame, minW, minH, maxW, maxH)
minW = minW or 4
minH = minH or 4
maxW = maxW or 99
maxH = maxH or 99
local btn = frame:addButton()
:setPosition("parent.w", "parent.h")
:setSize(1, 1)
:setText("/")
:setForeground(colors.blue)
:setBackground(colors.black)
:onDrag(function(self, event, btn, xOffset, yOffset)
local w, h = frame:getSize()
local wOff, hOff = w, h
if(w+xOffset-1>=minW)and(w+xOffset-1<=maxW)then
wOff = w+xOffset-1
end
if(h+yOffset-1>=minH)and(h+yOffset-1<=maxH)then
hOff = h+yOffset-1
end
frame:setSize(wOff, hOff)
end)
end
makeResizeable(sub, 8, 4)
sub:addLabel():setText("Hello World")
basalt.autoUpdate()
```
</details>
<br>
<video width="600" controls autoplay loop muted>
<source src="./_media/resizable-frames.mp4" type="video/mp4">
</video>
### Scrollable frames
Another important feature of frames is the possibility to make them scrollable. Basalt only provides vertical scrolling for frames. If you want to make horizontal scrolling possible, you need to do it yourself. Also, if you're using :setScrollable() the amount to scroll is based on the object's y-position + height - you can change this by using :setScrollAmount(amount). Only count's for the basalt implementation of scrollable frames.
<details>
<summary>Click here to show code</summary>
```lua
local basalt = require("basalt")
local main = basalt.createFrame():setTheme({FrameBG = colors.black, FrameFG = colors.lightGray})
-- Vertical scrolling is pretty simple, as you can tell:
local sub1 = main:addFrame():setScrollable():setSize(20, 15):setPosition(2, 2)
sub1:addLabel():setPosition(3, 2):setText("Scrollable")
sub1:addLabel():setPosition(3, 12):setText("Inside")
sub1:addLabel():setPosition(3, 20):setText("Outside")
-- Here we create a custom scroll event as you can see we dont add a :setScrollable() method to our frame, instead we add a custom scroll event
local objects = {}
local sub2 = main:addFrame():setPosition(23, 2):setSize(25, 5):onScroll(function(self, event, dir)
local maxScroll = 0
for k,v in pairs(objects)do -- here we iterate trough every object and get their x position + width this way we can find out what's the maximum allowed value to scroll
local x = v:getX()
local w = v:getWidth()
maxScroll = x + w > maxScroll and x + w or maxScroll -- if you don't understand this line, http://lua-users.org/wiki/TernaryOperator
end
local xOffset = self:getOffset()
if(xOffset+dir>=0 and xOffset+dir<=maxScroll-self:getWidth())then
self:setOffset(xOffset+dir, 0)
end
end)
-- Because we need to iterate the objects, we add them into a table.
table.insert(objects, sub2:addButton():setPosition(2, 2):setText("Scrollable"))
table.insert(objects, sub2:addButton():setPosition(16, 2):setText("Inside"))
table.insert(objects, sub2:addButton():setPosition(30, 2):setText("Outside"))
basalt.autoUpdate()
```
</details>
<br>
<video width="600" controls autoplay loop muted>
<source src="./_media/scrollable-frames.mp4" type="video/mp4">
</video>

View File

@@ -10,6 +10,7 @@ Its default position is always 1, 1 (based on it's parent frame). The default an
|[isVisible](objects/Object/isVisible.md)|Returns if the object is currently visible
|[enable](objects/Object/enable.md)|Listens to incoming events
|[disable](objects/Object/disable.md)|Ignores all incoming events
|[remove](objects/Object/remove.md)|Removes the children object from it's parent object
|[setPosition](objects/Object/setPosition.md)|Changes the position (x,y)
|[getPosition](objects/Object/getPosition.md)|Returns the current position
|[setBackground](objects/Object/setBackground.md)|Changes the object's background
@@ -40,6 +41,8 @@ This is a list of all available events for all objects:
|[onRelease](objects/Object/onRelease.md)|Fires as soon as the mouse button gets released
|[onScroll](objects/Object/onScroll.md)|Fires as soon as you scroll with the mousewheel
|[onDrag](objects/Object/onDrag.md)|Fires as soon as the object is beeing dragged
|[onHover](objects/Object/onHover.md)|CraftOS-PC - fires when the mouse hovers over a object
|[onLeave](objects/Object/onLeave.md)|CraftOS-PC - fires when the mouse leaves a object
|[onKey](objects/Object/onKey.md)|Fires when the object is focused and a keyboard key has been clicked
|[onChar](objects/Object/onChar.md)|Fires when the object is focused and a character has been clicked
|[onKeyUp](objects/Object/onKeyUp.md)|Fires when the object is focused and a keyboard key has been released

View File

@@ -1,4 +1,7 @@
# Object
## disable
Disables the object's event listeners
This will disable the object. Which means it doesn't listen to any events anymore.
This will disable the object. Which means it doesn't listen to any events anymore.

View File

@@ -1,4 +1,7 @@
# Object
## enable
Enables the object's event listeners
If the object's is disabled, it will stop listening to incoming events, this will reenable it.
If the object's is disabled, it will stop listening to incoming events, this will reenable it.

View File

@@ -1,16 +1,24 @@
# Object
## getAbsolutePosition
Converts the relative coordinates into absolute coordinates
#### Parameters:
### Parameters
1. `number|nil` x
2. `number|nil` y
#### Returns:
### Returns
1. `object` The object in use
#### Usage:
### Usage
* Creates a frame and a button and prints the button's absolute position to the debug console
```lua
local mainFrame = basalt.createFrame():setPosition(3,3)
local aButton = mainFrame:addButton():setSize(8,1):setPosition(4,2)
basalt.debug(aButton:getAbsolutePosition()) -- returns 7,5 (frame coords + own coords) instead of 4,2
```
```

View File

@@ -1,16 +1,23 @@
# Object
## getAnchorPosition
Converts the x and y coordinates into the anchor coordinates of the object
#### Parameters:
### Parameters
1. `number|nil` x
2. `number|nil` y, if nothing it uses the object's x, y
#### Returns:
#### Returns
1. `number` x
2. `number` y
#### Usage:
#### Usage
* Prints the anchor position to the debug console
```lua
local mainFrame = basalt.createFrame():setSize(15,15)
local aButton = mainFrame:addButton()
@@ -18,4 +25,4 @@ local aButton = mainFrame:addButton()
:setSize(8,1)
:setPosition(1,1)
basalt.debug(aButton:getAnchorPosition()) -- returns 7,14 (framesize - own size) instead of 1,1
```
```

View File

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

View File

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

View File

@@ -1,11 +1,17 @@
# Object
## getName
Returns the given name of the object
#### Returns:
### Returns
1. `string` name
#### Usage:
#### Usage
* Prints name of object to debug window
```lua
local main = basalt.createFrame()
basalt.debug(main:getName()) -- returns the uuid
@@ -14,4 +20,4 @@ basalt.debug(main:getName()) -- returns the uuid
```lua
local main = basalt.createFrame("myFirstMainFrame")
basalt.debug(main:getName()) -- returns myFirstMainFrame
```
```

View File

@@ -1,6 +1,10 @@
# Object
## getPosition
Returns the object's position
#### Returns:
### Returns
1. `number` x
2. `number` y

View File

@@ -1,6 +1,10 @@
# Object
## getSize
Returns the object's size
#### Returns:
### Returns
1. `number` w
2. `number` h

View File

@@ -1,12 +1,19 @@
# Object
## getValue
Returns the currently saved value
#### Returns:
### Returns
1. `any` Object's value
#### Usage:
### Usage
* Prints the value of the checkbox to the debug console
```lua
local mainFrame = basalt.createFrame()
local aCheckbox = mainFrame:addCheckbox():setValue(true)
basalt.debug(aCheckbox:getValue()) -- returns true
```
```

View File

@@ -1,15 +1,22 @@
# Object
## hide
Hides the object
#### Returns:
### Returns
1. `object` The object in use
#### Usage:
#### Usage
* Hides a frame
```lua
local mainFrame = basalt.createFrame()
local button = mainFrame:addButton():setText("Close"):onClick(function() mainFrame:hide() end)
```
```xml
<button visible="false" />
```
```

View File

@@ -1,13 +1,19 @@
# Object
## isFocused
Returns if the object is currently the focused object of the parent frame
#### Returns:
### Returns
1. `boolean` Whether the object is focused
#### Usage:
#### Usage
* Prints whether the button is focused to the debug console
```lua
local mainFrame = basalt.createFrame()
local aButton = mainFrame:addButton()
basalt.debug(aButton:isFocused()) -- shows true or false as a debug message
```
```

View File

@@ -1,12 +1,19 @@
# Object
## isVisible
Returns if the object is currently visible
#### Returns:
### Returns
1. `boolean`
#### Usage:
#### Usage
* Prints boolean visibility of object to debug console
```lua
local mainFrame = basalt.createFrame()
local aButton = mainFrame:addButton():setSize(5,8)
basalt.debug(aButton:isVisible()) -- returns true
```
```

View File

@@ -1,5 +1,9 @@
# onChange
`onChange(self)`<br>
# Object - Event
## onChange
`onChange(self)`
This is a custom event which gets triggered as soon as the function :setValue() is called. This function is also called by basalt, for example if you change the input, textfield or checkbox (or all the different types of lists) objects.
Here is a example on how to add a onChange event to your input, and also another example for your checkbox:
@@ -25,4 +29,4 @@ end
aInput:onChange(checkInput)
aCheckbox:onChange(checkCheckbox)
```
```

View File

@@ -1,6 +1,9 @@
# onChar
# Object - Event
## onChar
`onChar(self, event, char)`
`onChar(self, event, char)`<br>
The computercraft event which triggers this method is `char`.
The char event always happens after the key event (just like in cc:tweaked)

View File

@@ -1,5 +1,7 @@
# onClick
`onClick(self, event, button, x, y)`<br>
`onClick(self, event, button, x, y)`
The computercraft event which triggers this method is `mouse_click` and `monitor_touch`.
Here is a example on how to add a onClick event to your button:
@@ -20,6 +22,7 @@ button:onClick(buttonOnClick)
```
Here is also a example on how you could create double clicks:
```lua
local basalt = require("basalt")
local doubleClickMaxTime = 0.25 -- in seconds
@@ -44,4 +47,4 @@ end
createDoubleClick(button, debugSomething) -- this is how you will create a double click.
basalt.autoUpdate()
```
```

View File

@@ -1,5 +1,9 @@
# onClickUp
`onClickUp(self, event, button, x, y)`<br>
# Object - Event
## onClickUp
`onClickUp(self, event, button, x, y)`
The computercraft event which triggers this method is `mouse_up`.
Here is a example on how to add a onClickUp event to your button:
@@ -22,4 +26,4 @@ function buttonOnRelease(self, button, x, y)
basalt.debug("Button got released!")
end
button:onClickUp(buttonOnRelease)
```
```

View File

@@ -1,8 +1,13 @@
# onDrag
`onDrag(self, event, button, x, y, xOffset, yOffset)`<br>
# Object - Event
## onDrag
`onDrag(self, event, button, x, y, xOffset, yOffset)`
The computercraft event which triggers this method is `mouse_drag`.
This is a example on how you would create a movable button:
```lua
local basalt = require("basalt")
@@ -21,6 +26,7 @@ basalt.autoUpdate()
```
Another example on how you could change the frame's offset by dragging around.
```lua
local basalt = require("basalt")
@@ -43,6 +49,7 @@ basalt.autoUpdate()
```
Also very interesting is a button where you are able to resize the frame just by dragging the button.
```lua
local basalt = require("basalt")
@@ -57,7 +64,7 @@ local dragButton = sub:addButton()
:setSize(1,1)
:setText("/")
:onDrag(function(self, button, x, y, xOffset, yOffset)
sub:setSize(-xOffset, -yOffset, true)
sub:setSize(-xOffset, -yOffset, true)
end)
basalt.autoUpdate()

View File

@@ -1,4 +1,6 @@
# onEvent
# Object - Event
## onEvent
`onEvent(self, event, ...)`
@@ -17,4 +19,4 @@ main:onEvent(function(event, side, channel, replyChannel, message, distance)
basalt.debug("Mesage received: "..tostring(message))
end
end)
```
```

View File

@@ -1,5 +1,9 @@
# onGetFocus
`onGetFocus(self)`<br>
# Object - Event
## onGetFocus
`onGetFocus(self)`
This event gets triggered as soon as the object is the currently focused object.
```lua

View File

@@ -0,0 +1,24 @@
# Object - Event
## onHover
`onHover(self, event, button, x, y)`
The computercraft event which triggers this method is `mouse_move` - only available in [CraftOS-PC](https://www.craftos-pc.cc).
Here is a example on how to add a onHover event to your button:
```lua
local basalt = require("basalt")
local main = basalt.createFrame()
local button = main:addButton()
:setPosition(3,3)
:setSize(12,3)
:setText("Hover")
function buttonOnHover()
basalt.debug("The mouse hovers over the button!")
end
button:onHover(buttonOnHover)
```

View File

@@ -1,5 +1,9 @@
# onKey
`onKey(self, event, key)`<br>
# Object - Event
## onKey
`onKey(self, event, key)`
The computercraft event which triggers this method is `key` and `char`.
Here is a example on how to add a onKey event to your frame:
@@ -19,4 +23,4 @@ function openSubFrame(self, event, key)
end
end
main:onKey(openSubFrame)
```
```

View File

@@ -1,5 +1,9 @@
# onKeyUp
`onKeyUp(self, event, key)`<br>
# Object - Event
## onKeyUp
`onKeyUp(self, event, key)`
The computercraft event which triggers this method is `key_up`.
Here is a example on how to add a onKeyUp event to your frame:
@@ -18,4 +22,4 @@ function openSubFrame(self, event, key)
end
end
main:onKeyUp(openSubFrame)
```
```

View File

@@ -0,0 +1,24 @@
# Object - Event
## onLeave
`onLeave(self, event, button, x, y)`
The computercraft event which triggers this method is `mouse_move` - only available in [CraftOS-PC](https://www.craftos-pc.cc).
Here is a example on how to add a onLeave event to your button:
```lua
local basalt = require("basalt")
local main = basalt.createFrame()
local button = main:addButton()
:setPosition(3,3)
:setSize(12,3)
:setText("Leave")
function buttonOnLeave()
basalt.debug("The mouse left the button!")
end
button:onLeave(buttonOnLeave)
```

View File

@@ -1,5 +1,9 @@
# onLoseFocus
`onLoseFocus(self)`<br>
# Object - Event
## onLoseFocus
`onLoseFocus(self)`
This event gets triggered as soon as the object loses its focus.
```lua
@@ -13,4 +17,4 @@ local aButton = main:addButton()
basalt.debug("Please come back...")
end
)
```
```

View File

@@ -1,5 +1,9 @@
# onRelease
`onRelease(self, event, button, x, y)`<br>
# Object - Event
## onRelease
`onRelease(self, event, button, x, y)`
The computercraft event which triggers this method is `mouse_up`.
The difference between onRelease and :onClickUp is that :onRelease is called even when the mouse is no longer over the object, while :onClickUp is only called when the mouse is over the object.
@@ -24,4 +28,4 @@ function buttonOnRelease(self, button, x, y)
basalt.debug("Button got released!")
end
button:onRelease(buttonOnRelease)
```
```

View File

@@ -0,0 +1,22 @@
# Object - Event
## onReposition
`onReposition(self)`
This is a custom event which gets triggered as soon as the object gets repositioned (for example by dynamic value).
Here is a example on how to add a onReposition event to your button:
```lua
local basalt = require("basalt")
local main = basalt.createFrame()
local aButton = main:addButton():setPosition(3,3)
local function onButtonReposition(self)
self:setSize(self:getWidth() - self:getX(), 3)
end
aButton:onReposition(onButtonReposition)
```

View File

@@ -1,6 +1,9 @@
# onResize
# Object - Event
## onResize
`onResize(self)`
`onResize(self)`<br>
This is a custom event which gets triggered as soon as the parent frame gets resized.
Here is a example on how to add a onResize event to your button:

View File

@@ -1,5 +1,9 @@
# onScroll
`onScroll(self, event, direction, x, y)`<br>
# Object - Event
## onScroll
`onScroll(self, event, direction, x, y)`
The computercraft event which triggers this method is `mouse_scroll`.
Here is a example on how to add a onScroll event to your button:
@@ -17,4 +21,4 @@ function buttonOnScroll(self, direction, x, y)
basalt.debug("Someone scrolls on me!")
end
button:onScroll(buttonOnScroll)
```
```

View File

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

View File

@@ -1,14 +1,21 @@
# Object
## setAnchor
Sets the anchor of the object
#### Parameters:
### Parameters
1. `string` Anchor sides `("topLeft" "top", "topRight", "right", "bottomRight", "bottom", "bottomLeft", "left", "center")`
#### Returns:
### Returns
1. `object` The object in use
#### Usage:
### Usage
* Sets the button to have an anchor of `bottomRight`
```lua
local mainFrame = basalt.createFrame():show()
local aButton = mainFrame:addButton()
@@ -16,6 +23,7 @@ local aButton = mainFrame:addButton()
:setSize(8,1)
:setPosition(-8,1)
```
```xml
<button anchor="bottomRight" />
```
```

View File

@@ -1,16 +1,27 @@
## setBackground
Changes the object background color, if you set the value to false the background wont be visible. For example you could see trough a frame.
#### Parameters:
1. `number|color` Background color
# Object
## setBackground
Changes the object background color, if you set the value to false the background wont be visible. For example you could see trough a frame.
### Parameters
1. `number|color` Background color
1. `char` background symbol you want to draw (optional)
1. `number|color` Background symbol color (optional)
### Returns
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a frame, and sets its background color to `colors.gray`
### Usage
* Creates a frame, and sets its background color to `colors.gray`, also sets a background symbol with color black.
```lua
local mainFrame = basalt.createFrame():setBackground(colors.gray)
local mainFrame = basalt.createFrame():setBackground(colors.gray, "#", colors.black)
```
```xml
<button bg="gray" />
```
```

View File

@@ -1,16 +1,24 @@
# Object
## setBorder
Sets the border of that objects, if false the border will be removed<br>
Sets the border of that objects, if false the border will be removed
Default: false
#### Parameters:
### Parameters
1. `number|color` Border color
2. `string` optional - sides. If you don't set sides, all 4 sides will have a border
#### Returns:
### Returns
1. `object` The object in use
#### Usage:
### Usage
* Sets the border to green and shows it:
```lua
local mainFrame = basalt.createFrame()
local subFrame = mainFrame:addFrame()
@@ -18,6 +26,7 @@ local subFrame = mainFrame:addFrame()
:setSize(18,6)
:setBorder(colors.green, "left", "right", "bottom")
```
```xml
<frame width="18" height="6" borderColor="green" movable="true" />
```
```

View File

@@ -1,13 +1,20 @@
## setFocus
# Object
## setFocus
Sets the object to be the focused object.
If you click on an object, it's normally automatically the focused object. For example, if you call :show() on a frame, and you want this particular frame to be in
the foreground, you should also use :setFocus()
#### Returns:
### Returns
1. `object` The object in use
#### Usage:
### Usage
* Sets the button to the focused object
```lua
local mainFrame = basalt.createFrame()
local aButton = mainFrame:addButton():setFocus()
```
```

View File

@@ -1,16 +1,25 @@
# Object
## setForeground
Changes the object text color
#### Parameters:
### Parameters
1. `number|color` Foreground color
#### Returns:
### Returns
1. `object` The object in use
#### Usage:
### Usage
* Creates a frame, and sets its foreground color to `colors.green`
```lua
local mainFrame = basalt.createFrame():setForeground(colors.green)
```
```xml
<button fg="green" />
```
```

View File

@@ -1,13 +1,21 @@
# Object
## setParent
Sets the parent frame of the object
#### Parameters:
### Parameters
1. `frame` The to-be parent frame
#### Returns:
### Returns
1. `object` The object in use
#### Usage:
### Usage
* Sets the parent frame of the random frame, adding it to the main frame when the button is clicked"
```lua
local mainFrame = basalt.createFrame()
local aRandomFrame = basalt.createFrame()
@@ -16,4 +24,4 @@ local aButton = mainFrame:addButton():onClick(
aRandomFrame:setParent(mainFrame)
end
)
```
```

View File

@@ -1,28 +1,39 @@
# Object
## setPosition
Changes the position relative to its parent frame
#### Parameters:
### Parameters
1. `number|string` x coordinate as number or dynamicvalue as string
2. `number|string` y coordinate as number or dynamicvalue as string
3. `boolean` Whether it will add/remove to the current coordinates instead of setting them
#### Returns:
### Returns
1. `object` The object in use
#### Usage:
### Usage
* Sets the Buttons position to an x coordinate of 2 with a y coordinate of 3
```lua
local mainFrame = basalt.createFrame()
mainFrame:addButton():setPosition(2,3)
```
```xml
<button x="2" y="3" />
```
if you prefer to use dynamic values:
```lua
local mainFrame = basalt.createFrame()
mainFrame:addButton():setPosition("parent.w * 0.5", 23)
```
```xml
<button x="parent.w * 0.5" y="3" />
```
```

View File

@@ -1,14 +1,21 @@
# Object
## setShadow
Sets the shadow color - default: false
#### Parameters:
### Parameters
1. `number|color` Shadow color
#### Returns:
#### Returns
1. `object` The object in use
#### Usage:
#### Usage
* Sets the shadow to green and shows it:
```lua
local mainFrame = basalt.createFrame()
local subFrame = mainFrame:addFrame()
@@ -16,7 +23,9 @@ local subFrame = mainFrame:addFrame()
:setSize(18,6)
:setShadow(colors.green)
```
Or:
Or:
```xml
<frame width="18" height="6" shadowColor="green" movable="true" />
```
```

View File

@@ -1,18 +1,27 @@
# Object
## setSize
Changes the object size
#### Parameters:
### Parameters
1. `number|string` width as number or dynamicvalue as string
2. `number|string` height as number or dynamicvalue as string
#### Returns:
### Returns
1. `object` The object in use
#### Usage:
### Usage
* Sets the frame to have a width of 15 and a height of 12
```lua
local mainFrame = basalt.createFrame()
local subFrame = mainFrame:addFrame():setSize(15,12)
```
```xml
<frame width="15" height="12" />
```
```

View File

@@ -1,17 +1,26 @@
# Object
## setValue
Sets the value of that object (input, label, checkbox, textfield, scrollbar,...)
#### Parameters:
### Parameters
1. `any` Value to set the object to
#### Returns:
### Returns
1. `object` The object in use
#### Usage:
### Usage
* Creates a checkbox and ticks it
```lua
local mainFrame = basalt.createFrame()
local aCheckbox = mainFrame:addCheckbox():setValue(true)
```
```xml
<checkbox value="true" />
```
```

View File

@@ -1,19 +1,28 @@
# Object
## setZIndex
Sets the z-index. Higher value means higher draw/event priority. You can also add multiple objects to the same z-index, if so the last added object will have the highest priority.
#### Parameters:
### Parameters
1. `number` z-index
#### Returns:
### Returns
1. `object` The object in use
#### Usage:
### Usage
* Sets the buttons z-index to `1` and the labels z-index to `2`
```lua
local mainFrame = basalt.createFrame()
local aButton = mainFrame:addButton():setZIndex(1):setPosition(2,2)
local aLabel = mainFrame:addButton():setZIndex(2):setPosition(2,2):setText("I am a label!")
```
```xml
<button x="2" y="2" zIndex="1" />
<label x="2" y="2" text="I am a label!" zIndex="2" />
```
```

View File

@@ -1,15 +1,23 @@
# Object
## show
Shows the object (only if the parent frame is already visible)
#### Returns:
### Returns
1. `object` The object in use
#### Usage:
### Usage
* Shows a frame
```lua
local mainFrame = basalt.createFrame()
local button = mainFrame:addButton()
button:show()
```
```xml
<button visible="true" />
```
```

View File

@@ -1,10 +1,10 @@
With panes you are able to create background without any functionality
Panes are here to do some visual background modifying, without listening (by default) to any events.
Because panes don't have any unique functionality, there is also no method list for them.
Because panes don't have any unique functionality, there is also no method list for them.
[Object](objects/Object.md) methods also apply for panes.
## Example:
## Example
```lua
local mainFrame = basalt.createFrame()
@@ -13,6 +13,29 @@ aPane:setSize(30, 10)
aPane:setBackground(colors.yellow)
aPane:show()
```
```xml
<pane width="30" height="10" bg="yellow" />
```
```
### Other examples
!["pane-example-1"](../_media/pane-example-1.png)
```lua
main:addPane():setSize(15, 8):setPosition(2, 2):setBackground(colors.red)
main:addPane():setSize(15, 8):setPosition(18, 2):setBackground(colors.blue, "#")
main:addPane():setSize(15, 8):setPosition(17 * 2, 2):setBackground(colors.green, "#", colors.orange)
```
You could also create a 1-line height pane with dynamic width:
!["pane-example-2"](../_media/pane-example-2.png)
```lua
main:addPane():setSize("parent.w - 2", 1):setPosition(2, 2):setBackground(false, "\140", colors.blue)
main:addPane():setSize("parent.w - 2", 1):setPosition(2, 4):setBackground(colors.black, "\45", colors.red)
main:addPane():setSize("parent.w - 2", 1):setPosition(2, 6):setBackground(false, "\183", colors.purple)
```
You can also do that in y instead of x direction.

View File

@@ -12,6 +12,7 @@ Program objects are here for opening other executable programs in your main prog
|[injectEvent](objects/Program/injectEvent.md)|Injects a event into the program
|[injectEvents](objects/Program/injectEvents.md)|Injects a table of events
|[getQueuedEvents](objects/Program/getQueuedEvents.md)|Returns currently queued events
|[setEnviroment](objects/Program/setEnviroment.md)|Changes the default enviroment to a custom one
# Events

View File

@@ -0,0 +1,10 @@
## setEnviroment
Changes the default enviroment to a custom enviroment
#### Parameters:
1. `table` - Enviroment table
#### Returns:
1. `program` Program in use

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2737
docs/versions/latest.lua Normal file

File diff suppressed because one or more lines are too long