Compare commits
46 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bb921c57cd | ||
|
|
2b85ab9746 | ||
|
|
29ebd7d4d7 | ||
|
|
8ab7bc4bde | ||
|
|
1b8f62ce41 | ||
|
|
61e38d89e8 | ||
|
|
a0db5ecb61 | ||
|
|
3ef7aa91bf | ||
|
|
09e8589938 | ||
|
|
e9aba2498b | ||
|
|
20ceb6b56f | ||
|
|
6d2956f3bf | ||
|
|
91e42e096c | ||
|
|
5f00dfe401 | ||
|
|
2c4c059a70 | ||
|
|
923b570d48 | ||
|
|
5499057e7e | ||
|
|
d6091b312c | ||
|
|
f19c0ebb49 | ||
|
|
01b83822b1 | ||
|
|
c81f24cca2 | ||
|
|
ed894cb390 | ||
|
|
355db9a82c | ||
|
|
8112378c70 | ||
|
|
a181496052 | ||
|
|
636ed0001f | ||
|
|
0e3da7eda5 | ||
|
|
3cf5adaef1 | ||
|
|
c0fab23cef | ||
|
|
7609708507 | ||
|
|
e2f2a2871d | ||
|
|
37dde881ad | ||
|
|
8f2e191fe3 | ||
|
|
15d8cb3781 | ||
|
|
8acb673f74 | ||
|
|
cfdca639db | ||
|
|
b34cdd8383 | ||
|
|
a74b8a3d9f | ||
|
|
ef480c3998 | ||
|
|
c3e97ae516 | ||
|
|
d78bb4d141 | ||
|
|
ab72f244ed | ||
|
|
4352d36831 | ||
|
|
04ad97ccbe | ||
|
|
6b2433e0a1 | ||
|
|
bf1b008084 |
144
Basalt/Frame.lua
144
Basalt/Frame.lua
@@ -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
|
||||
@@ -89,6 +92,7 @@ return function(name, parent, pTerm, basalt)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function getDeepObject(name)
|
||||
local o = getObject(name)
|
||||
if(o~=nil)then return o end
|
||||
@@ -240,11 +244,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 +331,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 +349,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 +414,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 +453,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 +478,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 +531,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 +601,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 +635,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)
|
||||
@@ -736,9 +826,7 @@ return function(name, parent, pTerm, basalt)
|
||||
if (events["other_event"][index] ~= nil) then
|
||||
for _, value in rpairs(events["other_event"][index]) do
|
||||
if (value.eventHandler ~= nil) then
|
||||
if (value:eventHandler(event, ...)) then
|
||||
return true
|
||||
end
|
||||
value:eventHandler(event, ...)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -747,6 +835,7 @@ return function(name, parent, pTerm, basalt)
|
||||
if(autoSize)and not(isMonitor)then
|
||||
if(self.parent==nil)then
|
||||
if(event=="term_resize")then
|
||||
self:sendEvent("basalt_resize", self, event, ...)
|
||||
self:setSize(termObject.getSize())
|
||||
autoSize = true
|
||||
end
|
||||
@@ -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
|
||||
|
||||
@@ -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,11 +108,25 @@ 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("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
|
||||
local tex, mode, infPlay
|
||||
if(xmlValue("texture", data)~=nil)then tex = xmlValue("texture", data) end
|
||||
if(xmlValue("mode", data)~=nil)then mode = xmlValue("mode", data) end
|
||||
if(xmlValue("texturePlay", data)~=nil)then infPlay = xmlValue("texturePlay", data) end
|
||||
local x, y
|
||||
if(xmlValue("x", data)~=nil)then x = xmlValue("x", data) end
|
||||
if(xmlValue("y", data)~=nil)then y = xmlValue("y", data) end
|
||||
if(x~=nil)or(y~=nil)then
|
||||
self:setPosition(x, y)
|
||||
end
|
||||
local w, h
|
||||
if(xmlValue("width", data)~=nil)then w = xmlValue("width", data) end
|
||||
if(xmlValue("height", data)~=nil)then h = xmlValue("height", data) end
|
||||
if(w~=nil)or(h~=nil)then
|
||||
self:setSize(w, h)
|
||||
end
|
||||
if(xmlValue("bg", data)~=nil)then self:setBackground(colors[xmlValue("bg", data)]) end
|
||||
if(xmlValue("bgSymbol", data)~=nil)then self:setBackground(self.bgColor, xmlValue("bgSymbol", data)) end
|
||||
if(xmlValue("bgSymbolColor", data)~=nil)then self:setBackground(self.bgColor, self.bgSymbol, colors[xmlValue("bgSymbolColor", data)]) end
|
||||
if(xmlValue("fg", data)~=nil)then self:setForeground(colors[xmlValue("fg", data)]) end
|
||||
if(xmlValue("value", data)~=nil)then self:setValue(colors[xmlValue("value", data)]) end
|
||||
if(xmlValue("visible", data)~=nil)then if(xmlValue("visible", data))then self:show() else self:hide() end end
|
||||
@@ -130,6 +155,9 @@ return function(name)
|
||||
if(xmlValue("onEvent", data)~=nil)then self:generateXMLEventFunction(self.onEvent, xmlValue("onEvent", data)) end
|
||||
if(xmlValue("onGetFocus", data)~=nil)then self:generateXMLEventFunction(self.onGetFocus, xmlValue("onGetFocus", data)) end
|
||||
if(xmlValue("onLoseFocus", data)~=nil)then self:generateXMLEventFunction(self.onLoseFocus, xmlValue("onLoseFocus", data)) end
|
||||
if(tex~=nil)then
|
||||
self:setTexture(tex, mode, infPlay)
|
||||
end
|
||||
self:updateDraw()
|
||||
return self
|
||||
end,
|
||||
@@ -195,11 +223,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 +275,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 +318,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 +353,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 +462,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 +516,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 +882,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 +899,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 +996,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;
|
||||
@@ -944,4 +1068,4 @@ return function(name)
|
||||
|
||||
object.__index = object
|
||||
return object
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,10 +1,17 @@
|
||||
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 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
|
||||
|
||||
return Basalt
|
||||
return Basalt
|
||||
|
||||
@@ -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
381
Basalt/libraries/bimg.lua
Normal 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
|
||||
97
Basalt/libraries/images.lua
Normal file
97
Basalt/libraries/images.lua
Normal file
@@ -0,0 +1,97 @@
|
||||
local sub,floor,rep = string.sub,math.floor,string.rep
|
||||
|
||||
local function loadNFPAsBimg(path)
|
||||
local bimg = {{}}
|
||||
local nfp = fs.open(path, "r")
|
||||
if(nfp~=nil)then
|
||||
for line in nfp.readLine do
|
||||
table.insert(bimg[1], {rep(" ",#line), rep(" ",#line), line})
|
||||
end
|
||||
nfp.close()
|
||||
return bimg
|
||||
end
|
||||
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,
|
||||
|
||||
}
|
||||
@@ -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()
|
||||
|
||||
@@ -1,17 +1,92 @@
|
||||
local splitString = function(str, sep)
|
||||
if sep == nil then
|
||||
sep = "%s"
|
||||
local sub,find,reverse = string.sub,string.find,string.reverse
|
||||
|
||||
local function splitString(str, delimiter)
|
||||
local result = {}
|
||||
if str == "" or delimiter == "" then
|
||||
return result
|
||||
end
|
||||
local start = 1
|
||||
local delim_start, delim_end = find(str, delimiter, start)
|
||||
while delim_start do
|
||||
table.insert(result, sub(str, start, delim_start - 1))
|
||||
start = delim_end + 1
|
||||
delim_start, delim_end = find(str, delimiter, start)
|
||||
end
|
||||
local t={}
|
||||
for v in string.gmatch(str, "([^"..sep.."]+)") do
|
||||
table.insert(t, v)
|
||||
end
|
||||
return t
|
||||
table.insert(result, sub(str, start))
|
||||
return result
|
||||
end
|
||||
|
||||
local relations = {[0] = {8, 4, 3, 6, 5}, {4, 14, 8, 7}, {6, 10, 8, 7}, {9, 11, 8, 0}, {1, 14, 8, 0}, {13, 12, 8, 0}, {2, 10, 8, 0}, {15, 8, 10, 11, 12, 14},
|
||||
{0, 7, 1, 9, 2, 13}, {3, 11, 8, 7}, {2, 6, 7, 15}, {9, 3, 7, 15}, {13, 5, 7, 15}, {5, 12, 8, 7}, {1, 4, 7, 15}, {7, 10, 11, 12, 14}}
|
||||
|
||||
local colourNum, exponents, colourChar = {}, {}, {}
|
||||
for i = 0, 15 do exponents[2^i] = i end
|
||||
do
|
||||
local hex = "0123456789abcdef"
|
||||
for i = 1, 16 do
|
||||
colourNum[hex:sub(i, i)] = i - 1
|
||||
colourNum[i - 1] = hex:sub(i, i)
|
||||
colourChar[hex:sub(i, i)] = 2 ^ (i - 1)
|
||||
colourChar[2 ^ (i - 1)] = hex:sub(i, i)
|
||||
|
||||
local thisRel = relations[i - 1]
|
||||
for i = 1, #thisRel do thisRel[i] = 2 ^ thisRel[i] end
|
||||
end
|
||||
end
|
||||
|
||||
local function getBestColourMatch(usage)
|
||||
local lastCol = relations[exponents[usage[#usage][1]]]
|
||||
|
||||
for j = 1, #lastCol do
|
||||
local thisRelation = lastCol[j]
|
||||
for i = 1, #usage - 1 do if usage[i][1] == thisRelation then return i end end
|
||||
end
|
||||
|
||||
return 1
|
||||
end
|
||||
|
||||
local function colsToChar(pattern, totals)
|
||||
if not totals then
|
||||
local newPattern = {}
|
||||
totals = {}
|
||||
for i = 1, 6 do
|
||||
local thisVal = pattern[i]
|
||||
local thisTot = totals[thisVal]
|
||||
totals[thisVal], newPattern[i] = thisTot and (thisTot + 1) or 1, thisVal
|
||||
end
|
||||
pattern = newPattern
|
||||
end
|
||||
|
||||
local usage = {}
|
||||
for key, value in pairs(totals) do usage[#usage + 1] = {key, value} end
|
||||
|
||||
if #usage > 1 then
|
||||
-- Reduce the chunk to two colours:
|
||||
while #usage > 2 do
|
||||
table.sort(usage, function (a, b) return a[2] > b[2] end)
|
||||
local matchToInd, usageLen = getBestColourMatch(usage), #usage
|
||||
local matchFrom, matchTo = usage[usageLen][1], usage[matchToInd][1]
|
||||
for i = 1, 6 do if pattern[i] == matchFrom then
|
||||
pattern[i] = matchTo
|
||||
usage[matchToInd][2] = usage[matchToInd][2] + 1
|
||||
end end
|
||||
usage[usageLen] = nil
|
||||
end
|
||||
|
||||
-- Convert to character. Adapted from oli414's function:
|
||||
-- http://www.computercraft.info/forums2/index.php?/topic/25340-cc-176-easy-drawing-characters/
|
||||
local data = 128
|
||||
for i = 1, #pattern - 1 do if pattern[i] ~= pattern[6] then data = data + 2^(i-1) end end
|
||||
return string.char(data), colourChar[usage[1][1] == pattern[6] and usage[2][1] or usage[1][1]], colourChar[pattern[6]]
|
||||
else
|
||||
-- Solid colour character:
|
||||
return "\128", colourChar[pattern[1]], colourChar[pattern[1]]
|
||||
end
|
||||
end
|
||||
|
||||
return {
|
||||
getTextHorizontalAlign = function(text, width, textAlign, replaceChar)
|
||||
text = string.sub(text, 1, width)
|
||||
text = sub(text, 1, width)
|
||||
local offset = width - string.len(text)
|
||||
if (textAlign == "right") then
|
||||
text = string.rep(replaceChar or " ", offset) .. text
|
||||
@@ -62,22 +137,25 @@ splitString = splitString,
|
||||
|
||||
createText = function(str, width)
|
||||
local uniqueLines = splitString(str, "\n")
|
||||
local lines = {}
|
||||
local result = {}
|
||||
for k,v in pairs(uniqueLines)do
|
||||
local line = ""
|
||||
local words = splitString(v, " ")
|
||||
for a,b in pairs(words)do
|
||||
if(#line+#b <= width)then
|
||||
line = line=="" and b or line.." "..b
|
||||
if(a==#words)then table.insert(lines, line) end
|
||||
if(#v==0)then table.insert(result, "") end
|
||||
while #v > width do
|
||||
local last_space = find(reverse(sub(v, 1, width)), " ")
|
||||
if not last_space then
|
||||
last_space = width
|
||||
else
|
||||
table.insert(lines, line)
|
||||
line = b:sub(1,width)
|
||||
if(a==#words)then table.insert(lines, line) end
|
||||
last_space = width - last_space + 1
|
||||
end
|
||||
local line = sub(v, 1, last_space)
|
||||
table.insert(result, line)
|
||||
v = sub(v, last_space + 1)
|
||||
end
|
||||
if #v > 0 then
|
||||
table.insert(result, v)
|
||||
end
|
||||
end
|
||||
return lines
|
||||
return result
|
||||
end,
|
||||
|
||||
getValueFromXML = function(name, tab)
|
||||
@@ -117,4 +195,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,
|
||||
}
|
||||
159
Basalt/main.lua
159
Basalt/main.lua
@@ -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)
|
||||
@@ -55,7 +68,7 @@ return function(...)
|
||||
local co = coroutine.create(f)
|
||||
local ok, result = coroutine.resume(co, ...)
|
||||
if(ok)then
|
||||
table.insert(schedules, co)
|
||||
table.insert(schedules, {co, result})
|
||||
else
|
||||
basaltError(result)
|
||||
end
|
||||
@@ -79,6 +92,10 @@ local getTheme = function(name)
|
||||
end
|
||||
|
||||
local bInstance = {
|
||||
getDynamicValueEventSetting = function()
|
||||
return basalt.dynamicValueEvents
|
||||
end,
|
||||
|
||||
getMainFrame = function()
|
||||
return mainFrame
|
||||
end,
|
||||
@@ -137,15 +154,26 @@ local bInstance = {
|
||||
end
|
||||
}
|
||||
|
||||
local function handleSchedules(event, p1, p2, p3, p4)
|
||||
local function handleSchedules(event, ...)
|
||||
if(#schedules>0)then
|
||||
local finished = {}
|
||||
for n=1,#schedules do
|
||||
if(schedules[n]~=nil)then
|
||||
if (coroutine.status(schedules[n]) == "suspended")then
|
||||
local ok, result = coroutine.resume(schedules[n], event, p1, p2, p3, p4)
|
||||
if not(ok)then
|
||||
basaltError(result)
|
||||
if (coroutine.status(schedules[n][1]) == "suspended")then
|
||||
if(schedules[n][2]~=nil)then
|
||||
if(schedules[n][2]==event)then
|
||||
local ok, result = coroutine.resume(schedules[n][1], event, ...)
|
||||
schedules[n][2] = result
|
||||
if not(ok)then
|
||||
basaltError(result)
|
||||
end
|
||||
end
|
||||
else
|
||||
local ok, result = coroutine.resume(schedules[n][1], event, ...)
|
||||
schedules[n][2] = result
|
||||
if not(ok)then
|
||||
basaltError(result)
|
||||
end
|
||||
end
|
||||
else
|
||||
table.insert(finished, n)
|
||||
@@ -176,8 +204,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 +225,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 +236,78 @@ 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, ...)
|
||||
handleSchedules(event, ...)
|
||||
drawFrames()
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
if(event == "monitor_touch") then
|
||||
if(monFrames[p1]~=nil)then
|
||||
monFrames[p1]:mouseHandler(1, p2, p3, true)
|
||||
activeFrame = monFrames[p1]
|
||||
if(monFrames[a[1]]~=nil)then
|
||||
monFrames[a[1]]:mouseHandler(1, a[2], a[3], true)
|
||||
activeFrame = monFrames[a[1]]
|
||||
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
|
||||
handleSchedules(event, ...)
|
||||
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, ...)
|
||||
handleSchedules(event, ...)
|
||||
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 +364,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
4
Basalt/module.lua
Normal file
@@ -0,0 +1,4 @@
|
||||
return function(path)
|
||||
local exists, content = pcall(require, path)
|
||||
return exists and content or nil
|
||||
end
|
||||
@@ -38,7 +38,7 @@ return function(name)
|
||||
end;
|
||||
|
||||
setText = function(self, text)
|
||||
base:setValue(text)
|
||||
base:setValue(tostring(text))
|
||||
self:updateDraw()
|
||||
return self
|
||||
end;
|
||||
@@ -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
|
||||
|
||||
@@ -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
214
Basalt/objects/Graphic.lua
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -705,50 +705,55 @@ return function(name, parent)
|
||||
end
|
||||
end
|
||||
end,
|
||||
|
||||
customEventHandler = function(self, event, ...)
|
||||
base.customEventHandler(self, event, ...)
|
||||
if (curProcess == nil) then
|
||||
return
|
||||
end
|
||||
if(event=="basalt_resize")then
|
||||
local w, h = pWindow.getSize()
|
||||
local pW, pH = self:getSize()
|
||||
if(w~=pW)or(h~=pH)then
|
||||
pWindow.basalt_resize(pW, pH)
|
||||
if not (curProcess:isDead()) then
|
||||
resumeProcess(self, "term_resize")
|
||||
end
|
||||
end
|
||||
pWindow.basalt_reposition(self:getAnchorPosition())
|
||||
|
||||
end
|
||||
end,
|
||||
|
||||
eventHandler = function(self, event, p1, p2, p3, p4)
|
||||
if(base.eventHandler(self, event, p1, p2, p3, p4))then
|
||||
if (curProcess == nil) then
|
||||
return
|
||||
end
|
||||
if(event=="dynamicValueEvent")then
|
||||
local w, h = pWindow.getSize()
|
||||
local pW, pH = self:getSize()
|
||||
if(w~=pW)or(h~=pH)then
|
||||
pWindow.basalt_resize(pW, pH)
|
||||
if not (curProcess:isDead()) then
|
||||
resumeProcess(self, "term_resize")
|
||||
end
|
||||
base.eventHandler(self, event, p1, p2, p3, p4)
|
||||
if (curProcess == nil) then
|
||||
return
|
||||
end
|
||||
if not (curProcess:isDead()) then
|
||||
if not (paused) then
|
||||
if(event ~= "terminate") then
|
||||
resumeProcess(self, event, p1, p2, p3, p4)
|
||||
end
|
||||
pWindow.basalt_reposition(self:getAnchorPosition())
|
||||
|
||||
end
|
||||
if not (curProcess:isDead()) then
|
||||
if not (paused) then
|
||||
if(event ~= "terminate") then
|
||||
resumeProcess(self, event, p1, p2, p3, p4)
|
||||
end
|
||||
if (self:isFocused()) then
|
||||
local obx, oby = self:getAnchorPosition()
|
||||
local xCur, yCur = pWindow.getCursorPos()
|
||||
if (self.parent ~= nil) then
|
||||
local w,h = self:getSize()
|
||||
if (obx + xCur - 1 >= 1 and obx + xCur - 1 <= obx + w - 1 and yCur + oby - 1 >= 1 and yCur + oby - 1 <= oby + h - 1) then
|
||||
self.parent:setCursor(pWindow.getCursorBlink(), obx + xCur - 1, yCur + oby - 1, pWindow.getTextColor())
|
||||
end
|
||||
if (self:isFocused()) then
|
||||
local obx, oby = self:getAnchorPosition()
|
||||
local xCur, yCur = pWindow.getCursorPos()
|
||||
if (self.parent ~= nil) then
|
||||
local w,h = self:getSize()
|
||||
if (obx + xCur - 1 >= 1 and obx + xCur - 1 <= obx + w - 1 and yCur + oby - 1 >= 1 and yCur + oby - 1 <= oby + h - 1) then
|
||||
self.parent:setCursor(pWindow.getCursorBlink(), obx + xCur - 1, yCur + oby - 1, pWindow.getTextColor())
|
||||
end
|
||||
end
|
||||
|
||||
if (event == "terminate") then
|
||||
resumeProcess(self, event)
|
||||
self.parent:setCursor(false)
|
||||
return true
|
||||
end
|
||||
if (event == "terminate") then
|
||||
resumeProcess(self, event)
|
||||
self.parent:setCursor(false)
|
||||
return true
|
||||
end
|
||||
else
|
||||
table.insert(queuedEvent, { event = event, args = { p1, p2, p3, p4 } })
|
||||
end
|
||||
else
|
||||
table.insert(queuedEvent, { event = event, args = { p1, p2, p3, p4 } })
|
||||
end
|
||||
return false
|
||||
end
|
||||
end,
|
||||
|
||||
@@ -793,11 +798,11 @@ 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,
|
||||
|
||||
}
|
||||
|
||||
return setmetatable(object, base)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
}
|
||||
@@ -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
|
||||
|
||||
|
||||
BIN
docs/_media/dynamic-frames.mp4
Normal file
BIN
docs/_media/dynamic-frames.mp4
Normal file
Binary file not shown.
BIN
docs/_media/frames-with-menubars.mp4
Normal file
BIN
docs/_media/frames-with-menubars.mp4
Normal file
Binary file not shown.
BIN
docs/_media/frames-with-sidebar.mp4
Normal file
BIN
docs/_media/frames-with-sidebar.mp4
Normal file
Binary file not shown.
BIN
docs/_media/pane-example-1.png
Normal file
BIN
docs/_media/pane-example-1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.0 KiB |
BIN
docs/_media/pane-example-2.png
Normal file
BIN
docs/_media/pane-example-2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 717 B |
BIN
docs/_media/resizable-frames.mp4
Normal file
BIN
docs/_media/resizable-frames.mp4
Normal file
Binary file not shown.
BIN
docs/_media/scrollable-frames.mp4
Normal file
BIN
docs/_media/scrollable-frames.mp4
Normal file
Binary file not shown.
@@ -1,4 +1,4 @@
|
||||
- Getting Started
|
||||
- [Home](Home)
|
||||
- [Quick Start](home/Quick-Start)
|
||||
- [Installer](home/installer)
|
||||
- [How To](home/How-To)
|
||||
- [Download](home/download)
|
||||
|
||||
@@ -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)
|
||||
|
||||
61
docs/home/How-To.md
Normal file
61
docs/home/How-To.md
Normal file
@@ -0,0 +1,61 @@
|
||||
# How-To
|
||||
|
||||
After downloading the project you can finally start creating your own program and use basalt. The first thing you want to use in your program is always:
|
||||
|
||||
```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 = main:addButton() --> Here we add our first button
|
||||
button:setPosition(4, 4) -- of course we want to change the default position of our button
|
||||
button:setSize(16, 3) -- and the default size.
|
||||
button:setText("Click me!") --> This method displays what the text of our button should look like
|
||||
|
||||
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()
|
||||
```
|
||||
@@ -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
36
docs/home/download.md
Normal 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
|
||||
@@ -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>
|
||||

|
||||
```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
|
||||
```
|
||||
@@ -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>
|
||||
|
||||
200
docs/install.lua
200
docs/install.lua
@@ -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)
|
||||
end
|
||||
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!")
|
||||
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,7 +365,11 @@ 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")or(string.lower(args[1])=="release")then
|
||||
installer.download("https://basalt.madefor.cc/versions/"..args[2] or "latest.lua", args[3] or "basalt.lua")
|
||||
end
|
||||
end
|
||||
|
||||
return installer
|
||||
return installer
|
||||
|
||||
@@ -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
|
||||
|
||||
30
docs/objects/Animation/addMode.md
Normal file
30
docs/objects/Animation/addMode.md
Normal 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()
|
||||
```
|
||||
16
docs/objects/Animation/onStart.md
Normal file
16
docs/objects/Animation/onStart.md
Normal 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()
|
||||
```
|
||||
36
docs/objects/Animation/setMode.md
Normal file
36
docs/objects/Animation/setMode.md
Normal 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
|
||||
@@ -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
|
||||
|
||||
18
docs/objects/Basalt/setMouseDragThrottle.md
Normal file
18
docs/objects/Basalt/setMouseDragThrottle.md
Normal 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)
|
||||
```
|
||||
20
docs/objects/Basalt/setMouseMoveThrottle.md
Normal file
20
docs/objects/Basalt/setMouseMoveThrottle.md
Normal 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)
|
||||
```
|
||||
@@ -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>
|
||||
|
||||
@@ -1,17 +1,22 @@
|
||||
## setTheme
|
||||
Sets the default theme of that frame children objects always try to get the theme of its parent frame, if it does not exist it goes to its parent parent frame, and so on until it reaches the basalt managers theme - which is sotred in theme.lua (Please checkout [theme](https://github.com/Pyroxenium/Basalt/blob/master/Basalt/theme.lua) for how it could look like.
|
||||
|
||||
#### Parameters:
|
||||
Sets the default theme, of that frame children objects always try to get the theme of its parent frame, if it does not exist it goes to its parent parent frame, and so on until it reaches the basalt manager's theme - which is stored in theme.lua (Please checkout [theme](https://github.com/Pyroxenium/Basalt/blob/master/Basalt/theme.lua) for how it could look like.
|
||||
|
||||
#### Parameters:
|
||||
|
||||
1. `table` theme layout look into [theme](https://github.com/Pyroxenium/Basalt/blob/master/Basalt/theme.lua) for a example
|
||||
|
||||
#### Returns:
|
||||
|
||||
1. `frame` The frame being used
|
||||
|
||||
#### Usage:
|
||||
* Creates a new base frame and adds a new theme which only changes the default color of buttons.
|
||||
|
||||
- Creates a new base frame and adds a new theme which only changes the default color of buttons.
|
||||
|
||||
```lua
|
||||
local myFrame = basalt.createFrame():setTheme({
|
||||
ButtonBG = colors.yellow,
|
||||
ButtonText = colors.red,
|
||||
})
|
||||
```
|
||||
```
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
The image object is for adding more advanced backgrounds.
|
||||
It also provides a :shrink() function, where you can shrink the images to smaller ones. This functionallity is fully provided by the blittle library created by Bomb Bloke. I did not ask for permission to add it into the framework. If the creator wants me to remove the blittle part, just text me on discord!
|
||||
|
||||
The image object is still not done. in the future i will provide more image formats.
|
||||
The image object is for adding more advanced backgrounds to your interface. It supports the loading of .nfp and .bimg images.
|
||||
|
||||
[Object](objects/Object.md) methods also apply for images.
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
|[loadImage](objects/Image/loadImage.md)|Adds a new object
|
||||
|[shrink](objects/Image/shrink.md)|Sets the top bar text and colors - deprecated
|
||||
|[loadImage](objects/Image/loadImage.md)|Loads an image from the specified file path
|
||||
|[setImage](objects/Image/setImage.md)|Set's a new image
|
||||
|[usePalette](objects/Image/usePalette.md)|Changes the used palette to the image prefered palette
|
||||
|[play](objects/Image/play.md)|Plays an animated image
|
||||
|[selectFrame](objects/Image/selectFrame.md)|Selects a specific frame in an animated image
|
||||
|[getMetadata](objects/Image/getMetadata.md)|Returns the metadata of the image
|
||||
|[getImageSize](objects/Image/getImageSize.md)|Returns the width and height of the image
|
||||
|[resizeImage](objects/Image/resizeImage.md)|Resizes the image to the specified dimensions
|
||||
|
||||
# About Bimg
|
||||
|
||||
Bimg is a custom image format that can be used in place of .nfp, it is a table which can store multiple frames and metadata. The frames can store text, background and foreground, which makes it possible to create any image you'd like. The image format is made by people from the Minecraft Computercraft Mods - Discord. Here's a Github page which explains how the Bimg format works: [bimg](https://github.com/SkyTheCodeMaster/bimg)
|
||||
|
||||
6
docs/objects/Image/getImageSize.md
Normal file
6
docs/objects/Image/getImageSize.md
Normal file
@@ -0,0 +1,6 @@
|
||||
## getImageSize
|
||||
Returns the current image size
|
||||
|
||||
#### Returns:
|
||||
1. `number` width
|
||||
2. `number` height
|
||||
9
docs/objects/Image/getMetadata.md
Normal file
9
docs/objects/Image/getMetadata.md
Normal file
@@ -0,0 +1,9 @@
|
||||
## getMetadata
|
||||
Returns the metadata set in the image
|
||||
|
||||
#### Parameter:
|
||||
|
||||
1. `string` the metadata key (for example: title, description, author, creator, data, width, height,...)
|
||||
|
||||
#### Returns:
|
||||
1. `any` metadata value
|
||||
@@ -1,18 +1,23 @@
|
||||
## loadImage
|
||||
loads a default .nfp file into the object.
|
||||
This method is used to load an image file into the image object.
|
||||
|
||||
#### Parameters:
|
||||
1. `string` the absolute file path
|
||||
|
||||
1. `path` the absolute file path
|
||||
|
||||
#### Returns:
|
||||
|
||||
1. `object` The object in use
|
||||
|
||||
#### Usage:
|
||||
|
||||
* Creates a default image and loads a test.nfp file
|
||||
|
||||
```lua
|
||||
local mainFrame = basalt.createFrame()
|
||||
local aImage = mainFrame:addImage():loadImage("test.nfp")
|
||||
```
|
||||
|
||||
```xml
|
||||
<image path="test.nfp" />
|
||||
```
|
||||
```
|
||||
|
||||
10
docs/objects/Image/play.md
Normal file
10
docs/objects/Image/play.md
Normal file
@@ -0,0 +1,10 @@
|
||||
## play
|
||||
Plays a bimg animation. This can only work if the bimg has more than 1 frame.
|
||||
|
||||
#### Parameters:
|
||||
|
||||
1. `boolean` If the image animation should play
|
||||
|
||||
#### Returns:
|
||||
|
||||
1. `object` The object in use
|
||||
19
docs/objects/Image/resizeImage.md
Normal file
19
docs/objects/Image/resizeImage.md
Normal file
@@ -0,0 +1,19 @@
|
||||
## resizeImage
|
||||
This method is used to resize a bimg image. It takes two parameters: the new width, and the new height. It is important to note that resizing images can result in a loss of quality, as the original pixel data is being transformed and resampled to fit the new dimensions. This is especially noticeable when increasing the size of an image, as new pixels must be generated to fill in the gaps. As a result, it is generally recommended to use the original image at its full size whenever possible, rather than resizing it.
|
||||
|
||||
#### Parameters:
|
||||
|
||||
1. `number` the new width
|
||||
2. `number` the new height
|
||||
|
||||
#### Returns:
|
||||
1. `object` The object in use
|
||||
|
||||
#### Usage:
|
||||
|
||||
* Creates a new image object, loads the image and changes it's size.
|
||||
|
||||
```lua
|
||||
local mainFrame = basalt.createFrame()
|
||||
local aImage = mainFrame:addImage():loadImage("test.bimg"):resizeImage(40, 20)
|
||||
```
|
||||
19
docs/objects/Image/selectFrame.md
Normal file
19
docs/objects/Image/selectFrame.md
Normal file
@@ -0,0 +1,19 @@
|
||||
## selectFrame
|
||||
The selectFrame method allows you to change the current frame of an image object. It takes a single parameter, the index of the frame you want to display.
|
||||
|
||||
#### Parameters:
|
||||
|
||||
1. `number` the frame index
|
||||
|
||||
#### Returns:
|
||||
|
||||
1. `object` The object in use
|
||||
|
||||
#### Usage:
|
||||
|
||||
* Creates a default image and loads a test.nfp file
|
||||
|
||||
```lua
|
||||
local mainFrame = basalt.createFrame()
|
||||
local aImage = mainFrame:addImage():loadImage("test.bimg"):selectFrame(2)
|
||||
```
|
||||
23
docs/objects/Image/setImage.md
Normal file
23
docs/objects/Image/setImage.md
Normal file
@@ -0,0 +1,23 @@
|
||||
## setImage
|
||||
Sets a new image
|
||||
|
||||
#### Parameter:
|
||||
|
||||
1. `table` A table in bimg or nfp format.
|
||||
1. `string` The format in which the image should be loaded (nfp or bimg)
|
||||
|
||||
#### Usage:
|
||||
|
||||
* Creates a default image and loads a test.nfp file
|
||||
|
||||
```lua
|
||||
local mainFrame = basalt.createFrame()
|
||||
|
||||
local bimg = {
|
||||
[1] = {
|
||||
{"Hello", "fffff", "33333"}
|
||||
}
|
||||
}
|
||||
|
||||
local aImage = mainFrame:addImage():setImage(bimg)
|
||||
```
|
||||
11
docs/objects/Image/usePalette.md
Normal file
11
docs/objects/Image/usePalette.md
Normal file
@@ -0,0 +1,11 @@
|
||||
## usePalette
|
||||
|
||||
Changes the palette colors of the image, if the bimg image has palette metadata.
|
||||
|
||||
#### Parameter:
|
||||
|
||||
1. `boolean` if the image should change the palette
|
||||
|
||||
#### Returns:
|
||||
|
||||
1. `object` The object in use
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
```
|
||||
```
|
||||
|
||||
@@ -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
|
||||
```
|
||||
```
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
# Object
|
||||
|
||||
## getBackground
|
||||
|
||||
Returns the current background color
|
||||
|
||||
#### Returns:
|
||||
### Returns
|
||||
|
||||
1. `number` color
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
# Object
|
||||
|
||||
## getForeground
|
||||
|
||||
Returns the current foreground color
|
||||
|
||||
#### Returns:
|
||||
### Returns
|
||||
|
||||
1. `number` color
|
||||
|
||||
@@ -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
|
||||
```
|
||||
```
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
# Object
|
||||
|
||||
## getPosition
|
||||
|
||||
Returns the object's position
|
||||
|
||||
#### Returns:
|
||||
### Returns
|
||||
|
||||
1. `number` x
|
||||
2. `number` y
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
# Object
|
||||
|
||||
## getSize
|
||||
|
||||
Returns the object's size
|
||||
|
||||
#### Returns:
|
||||
### Returns
|
||||
|
||||
1. `number` w
|
||||
2. `number` h
|
||||
|
||||
@@ -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
|
||||
```
|
||||
```
|
||||
|
||||
@@ -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" />
|
||||
```
|
||||
```
|
||||
|
||||
@@ -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
|
||||
```
|
||||
```
|
||||
|
||||
@@ -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
|
||||
```
|
||||
```
|
||||
|
||||
@@ -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)
|
||||
```
|
||||
```
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
```
|
||||
```
|
||||
|
||||
@@ -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)
|
||||
```
|
||||
```
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
```
|
||||
```
|
||||
|
||||
@@ -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
|
||||
|
||||
24
docs/objects/Object/onHover.md
Normal file
24
docs/objects/Object/onHover.md
Normal 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)
|
||||
```
|
||||
@@ -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)
|
||||
```
|
||||
```
|
||||
|
||||
@@ -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)
|
||||
```
|
||||
```
|
||||
|
||||
24
docs/objects/Object/onLeave.md
Normal file
24
docs/objects/Object/onLeave.md
Normal 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)
|
||||
```
|
||||
@@ -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
|
||||
)
|
||||
```
|
||||
```
|
||||
|
||||
@@ -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)
|
||||
```
|
||||
```
|
||||
|
||||
@@ -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)
|
||||
```
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
```
|
||||
```
|
||||
|
||||
@@ -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
|
||||
```
|
||||
```
|
||||
|
||||
@@ -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" />
|
||||
```
|
||||
```
|
||||
|
||||
@@ -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" />
|
||||
```
|
||||
```
|
||||
|
||||
@@ -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" />
|
||||
```
|
||||
```
|
||||
|
||||
@@ -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()
|
||||
```
|
||||
```
|
||||
|
||||
@@ -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" />
|
||||
```
|
||||
```
|
||||
|
||||
@@ -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
|
||||
)
|
||||
```
|
||||
```
|
||||
|
||||
@@ -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" />
|
||||
```
|
||||
```
|
||||
|
||||
@@ -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" />
|
||||
```
|
||||
```
|
||||
|
||||
@@ -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" />
|
||||
```
|
||||
```
|
||||
|
||||
@@ -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" />
|
||||
```
|
||||
```
|
||||
|
||||
@@ -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" />
|
||||
```
|
||||
```
|
||||
|
||||
@@ -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" />
|
||||
```
|
||||
```
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user