Posted 15 March 2015 - 04:12 PM
Hi guys,
I am writing my owm GUI API and there is a problem I can't solve. When run this code:
It throws this error:
The API is here:
Before you ask, all the apis have been initialized. If you don't believe me, check out this GitHub repo.
Thanks in advance and have a great afternoon (bulgarian time)
~Creator
PS: Line 330 is in the BetterPiant class section ;)/> BetterPaint is awesome!
This line:
In the BetterPaint.draw() function.
I am writing my owm GUI API and there is a problem I can't solve. When run this code:
Spoiler
--[[
Desktop in ComputerCraft
by Creator
for TheOS
]]--
--Variables--
local textutilsserialize = textutils.serialize
local textutilsunserialize = textutils.unserialize
local w,h = term.getSize()
local Settings = {}
local result = {}
local Main = {}
local QuickSettings = {}
--Functions--
local function readFile(_path)
local file = fs.open(_path,"r")
local data = file.readAll()
file.close()
return data
end
local function split(str,sep)
local buffer = {}
for token in str:gmatch(sep) do
buffer[#buffer+1] = token
end
return buffer
end
--Loading settings--
local buffer = readFile("TheOS/Desktop/Settings")
Settings = textutils.unserialize( buffer )
--Object table--
Main.ButtonTable = {
quickSettings = {
name = "quickSettings",
label = "^",
xPos = 1,
yPos = h,
xLength = 1,
yLength = 1,
xTextPos = 1,
yTextPos = 1,
fgColor = colors.white,
bgColor = Settings.bgColor,
returnValue = "quickSettings",
},
windowPlus = {
name = "windowPlus",
label = ">",
xPos = w,
yPos = 1,
xLength = 1,
yLength = 1,
xTextPos = 1,
yTextPos = 1,
fgColor = colors.white,
bgColor = Settings.bgColor,
returnValue = "windowPlus",
},
windowMinus = {
name = "windowMinus",
label = "<",
xPos = 1,
yPos = 1,
xLength = 1,
yLength = 1,
xTextPos = 1,
yTextPos = 1,
fgColor = colors.white,
bgColor = Settings.bgColor,
returnValue = "windowMinus",
},
}
QuickSettings.ButtonTable = {
Close = {
name = "Close",
label = "X",
xPos = w,
yPos = 1,
xLength = 1,
yLength = 1,
xTextPos = 1,
yTextPos = 1,
fgColor = colors.black,
bgColor = colors.white,
returnValue = "Close",
},
Right = {
name = "Right",
label = ">",
xPos = w-1,
yPos = 4,
xLength = 1,
yLength = 3,
xTextPos = 1,
yTextPos = 2,
fgColor = Settings.bgColor,
bgColor = colors.white,
returnValue = "Right",
},
Left = {
name = "Left",
label = "<",
xPos = 2,
yPos = 4,
xLength = 1,
yLength = 3,
xTextPos = 1,
yTextPos = 2,
fgColor = Settings.bgColor,
bgColor = colors.white,
returnValue = "Left",
}
}
QuickSettings.ColorFieldTable = {
TopBar = {
name = "TopBar",
xPos = 1,
yPos = 1,
xLength = w,
yLength = 1,
color = colors.white,
}
}
QuickSettings.BetterPaint = {
Restart = {
xPos = 4,
yPos = 2,
name = "Restart",
path = "TheOS/Desktop/QuickSettings/restart.ico",
yLength = 5,
xLength = 7,
returnValue = "reboot",
label = "Restart",
labelFg = colors.black,
labelBg = colors.lightGray,
},
Shutdown = {
xPos = 13,
yPos = 2,
name = "Shutdown",
path = "TheOS/Desktop/QuickSettings/shutdown.ico",
yLength = 5,
xLength = 7,
returnValue = "shutdown",
label = "Shutdown",
labelFg = colors.black,
labelBg = colors.lightGray,
},
}
--Initializing GUI components
local gui = Interact.Initialize()
local mainLayout = gui.Layout.new({xPos = 1,yPos = 1,xLength = w,yLength = h})
local quickSettingsLayout = gui.Layout.new({xPos = 1,yPos = h-7,xLength = w,yLength = h, nilClick = true})
--Initializing Buttons--
--Main--
local mainLayoutTable = {}
mainLayoutTable.Button = {}
for i,v in pairs(Main.ButtonTable) do
mainLayoutTable.Button[i] = gui.Button.new(Main.ButtonTable[i])
end
mainLayoutTable.mainBgColor = gui.BackgroundColor.new({color = Settings.bgColor})
--QuickSettings--
local quickSettingsLayoutTable = {}
quickSettingsLayoutTable.Button = {}
for i,v in pairs(QuickSettings.ButtonTable) do
quickSettingsLayoutTable.Button[i] = gui.Button.new(QuickSettings.ButtonTable[i])
end
quickSettingsLayoutTable.quickSettingsBgColor = gui.BackgroundColor.new({color = colors.lightGray})
quickSettingsLayoutTable.TopBar = gui.ColorField.new(QuickSettings.ColorFieldTable.TopBar)
quickSettingsLayoutTable.Restart = gui.BetterPaint.new(QuickSettings.BetterPaint.Restart)
quickSettingsLayoutTable.Shutdown = gui.BetterPaint.new(QuickSettings.BetterPaint.Shutdown)
--Initializing structures--
--Main--
for i,v in pairs(mainLayoutTable.Button) do
mainLayout:addButton(mainLayoutTable.Button[i]:returnData())
end
mainLayout:addBackgroundColor(mainLayoutTable.mainBgColor:returnData())
--QuickSettings--
for i,v in pairs(quickSettingsLayoutTable.Button) do
quickSettingsLayout:addButton(quickSettingsLayoutTable.Button[i]:returnData())
end
quickSettingsLayout:addBackgroundColor(quickSettingsLayoutTable.quickSettingsBgColor:returnData())
quickSettingsLayout:addColorField(quickSettingsLayoutTable.TopBar:returnData())
quickSettingsLayout:addBetterPaint(quickSettingsLayoutTable.Restart)
quickSettingsLayout:addBetterPaint(quickSettingsLayoutTable.Shutdown)
function writeTable()
file = fs.open("TheOS/Desktop/Settings","w")
file.write(textutilsserialize({
bgColor = colors.blue,
}))
file.close()
end
--writeTable()
--[[term.setCursorPos(1,1)
term.clear()
for i,v in pairs(quickSettingsLayout) do
print(i)
end
os.pullEvent()]]--
--Code--
while true do
mainLayout:draw()
local result = gui.eventHandler(mainLayout)
if result[1] == "Button" then
if result[2] == "quickSettings" then
quickSettingsLayout:draw()
local answer = gui.eventHandler(quickSettingsLayout)
if answer[1] == "Button" then
if answer[2] == "reboot" then
os.reboot()
elseif answer[2] == "shutdown" then
os.shutdown()
end
end
end
end
end
It throws this error:
Interact:330: attempt to perform arithmetic __add on nil and number
The API is here:
Spoiler
--[[
Interact API in ComputerCraft
by Creator
Complete rewrite in OOP
]]--
local textutilsserialize = textutils.serialize
local textutilsunserialize = textutils.unserialize
--Class declarations--
local Button = {}
local Layout = {}
local Toggle = {}
local BackgroundColor = {}
local ColorField = {}
local BetterPaint = {}
--Class Layout--
--Layout initialization function--
Layout.new = function(input)
local self = {}
setmetatable(self,{__index = Layout})
self.Button = {}
self.Toggle = {}
self.ColorField = {}
self.BetterPaint = {}
self.BackgroundColor = 1
self.xPos = input.xPos or 1
self.yPos = input.yPos or 1
self.xMax = input.xMax or 51
self.yMax = input.yMax or 19
self.nilClick = input.nilClick or false
return self
end
--Add element function--
Layout.addButton = function(self,_elementData)
self.Button[_elementData.name] = _elementData
end
Layout.addToggle = function(self,_elementData)
self.Toggle[_elementData.name] = _elementData
end
Layout.addBackgroundColor = function(self,_elementData)
self.BackgroundColor = _elementData.color
end
Layout.addColorField = function(self,_elementData)
self.ColorField[_elementData.name] = _elementData
end
Layout.addBetterPaint = function(self,_elementData)
self.BetterPaint[_elementData.name] = _elementData
end
Layout.draw = function(self)
local buttonFunctions = {}
local toggleFunctions = {}
local colorFieldFunctions = {}
local betterPaintFunctions = {}
setmetatable(buttonFunctions,{__index = Button})
setmetatable(toggleFunctions,{__index = Toggle})
setmetatable(colorFieldFunctions,{__index = ColorField})
setmetatable(betterPaintFunctions,{__index = BetterPaint})
paintutils.drawFilledBox(self.xPos,self.yPos,self.xMax,self.yMax,self.BackgroundColor)
for i,v in pairs(self.ColorField) do
colorFieldFunctions.draw(v,self.xPos,self.yPos)
end
for i,v in pairs(self.Button) do
buttonFunctions.draw(v,self.xPos,self.yPos)
end
for i,v in pairs(self.BetterPaint) do
betterPaintFunctions.draw(v,self.xPos,self.yPos)
end
for i,v in pairs(self.Toggle) do
toggleFunctions.draw(v,self.xPos,self.yPos)
end
end
--Class Button--
--Button initialization function
Button.new = function(input)
local self = {}
setmetatable(self,{__index = Button})
self.name = input.name
self.label = input.label
self.xPos = input.xPos
self.yPos = input.yPos
self.fgColor = input.fgColor
self.bgColor = input.bgColor
self.xLength = input.xLength
self.yLength = input.yLength
self.returnValue = input.returnValue
self.xTextPos = input.xTextPos
self.yTextPos = input.yTextPos
return self
end
--Draw function
Button.draw = function(self,layoutX,layoutY,addX,addY)
layoutX = layoutX or 0
layoutY = layoutY or 0
if self.moveX then
addX = addX or 0
else
addX = 0
end
if self.moveY then
addY = addY or 0
else
addY = 0
end
local finalX = self.xPos + layoutX + addX - 1
local finalY = self.yPos + layoutY + addY - 1
self.finalX = finalX
self.finalY = finalY
local newText
if #self.label > self.xLength then
newText = string.sub(self.label,1,self.xLength)
else
newText = self.label
end
paintutils.drawFilledBox(finalX,finalY,finalX+self.xLength-1,finalY+self.yLength-1,self.bgColor)
term.setTextColor(self.fgColor)
term.setCursorPos(finalX+self.xTextPos-1,finalY+self.yTextPos-1)
term.write(newText)
end
--Return function--
Button.returnData = function(self)
local toReturn = {}
for i,v in pairs(self) do
toReturn[i] = v
end
return toReturn
end
--Sample Input table--
example = [[
example = {
name = "quickSettings",
label = ">",
xPos = 1,
yPos = 3,
xLength = 1,
yLength = 6,
xTextPos = 1,
yTextPos = 1,
fgColor = colors.blue,
bgColor = colors.lightGray,
returnValue = "quickSettings",
},
]]
--Class Toggle--
--Initialize Toggle Object--
Toggle.new = function(input)
local self = {}
setmetatable(self,{__index = Toggle})
self.name = input.name or "randomName"
self.state = input.state or true
self.xPos = input.xPos or 1
self.yPos = input.yPos or 1
self.trueColor = input.trueColor or colors.green
self.falseColor = input.falseColor or colors.red
self.trueText = input.trueText or "T"
self.falseText = input.falseText or "F"
self.selectedBg = input.selectedBg or colors.gray
self.notSelectedBg = input.notSelectedBg or colors.lightGray
self.returnValue = input.returnValue or "mmmmmmm"
return self
end
Toggle.draw = function(self,layoutX,layoutY,addX,addY)
layoutX = layoutX or 0
layoutY = layoutY or 0
if self.moveX then
addX = addX or 0
else
addX = 0
end
if self.moveY then
addY = addY or 0
else
addY = 0
end
local finalX = self.xPos + layoutX + addX - 1
local finalY = self.yPos + layoutY + addY - 1
self.finalX = finalX
self.finalY = finalY
term.setCursorPos(finalX,finalY)
if self.state == false then
term.setBackgroundColor(self.notSelectedBg)
term.setTextColor(self.trueColor)
term.write(string.sub(self.trueText,1,1))
term.setBackgroundColor(self.selectedBg)
term.setTextColor(self.falseColor)
term.write(" "..string.sub(self.falseText,1,1).." ")
elseif self.state == true then
term.setBackgroundColor(self.selectedBg)
term.setTextColor(self.trueColor)
term.write(" "..string.sub(self.trueText,1,1).." ")
term.setBackgroundColor(self.notSelectedBg)
term.setTextColor(self.falseColor)
term.write(string.sub(self.falseText,1,1))
end
end
Toggle.returnData = function(self)
local toReturn = {}
for i,v in pairs(self) do
toReturn[i] = v
end
return toReturn
end
function Toggle.toggle(self)
if self.state == true then
self.state = false
else
self.state = true
end
end
function Toggle.getState(self)
return self.state
end
--BackgroundColor Class--
function BackgroundColor.new(input)
local self = {}
setmetatable(self,{__index = BackgroundColor})
self.color = input.color
return self
end
function BackgroundColor.setColor(self,color)
self.color = color
end
function BackgroundColor.returnData(self)
local toReturn = {}
for i,v in pairs(self) do
toReturn[i] = v
end
return toReturn
end
--ColorField Class--
function ColorField.new(input)
local self = {}
setmetatable(self,{__index = ColorField})
self.name = input.name
self.xPos = input.xPos
self.yPos = input.yPos
self.xLength = input.xLength
self.yLength = input.yLength
self.color = input.color
return self
end
function ColorField.draw(self,layoutX,layoutY,addX,addY)
layoutX = layoutX or 0
layoutY = layoutY or 0
if self.moveX then
addX = addX or 0
else
addX = 0
end
if self.moveY then
addY = addY or 0
else
addY = 0
end
local finalX = self.xPos + layoutX + addX - 1
local finalY = self.yPos + layoutY + addY - 1
self.finalX = finalX
self.finalY = finalY
paintutils.drawFilledBox(finalX,finalY,finalX+self.xLength-1,finalY+self.yLength-1,self.color)
end
function ColorField.returnData(self)
local toReturn = {}
for i,v in pairs(self) do
toReturn[i] = v
end
return toReturn
end
--BetterPaint Class--
function BetterPaint.new(input)
local self = {}
setmetatable(self,{__index = BetterPaint})
finalX = input.xPos
finalY = input.yPos
self.name = input.name
self.path = input.path
self.xLength = input.xLength
self.yLength = input.yLength
self.returnValue = input.returnValue
self.label = input.label
self.labelBg = input.labelBg
self.labelFg = input.labelFg
return self
end
function BetterPaint.returnData(self)
local toReturn = {}
for i,v in pairs(self) do
toReturn[i] = v
end
return toReturn
end
function BetterPaint.draw(self,layoutX,layoutY,addX,addY)
if layoutX == nil then layoutX = 0 end
if layoutY == nil then layoutY = 0 end
if self.moveX then
if laddX == nil then addX = 0 end
else
addX = 0
end
if self.moveY then
if addY == nil then addY = 0 end
else
addY = 0
end
local finalX = self.xPos + layoutX + addX - 1
local finalY = self.yPos + layoutY + addY - 1
self.finalX = finalX
self.finalY = finalY
paint.drawImage(self.path,finalX,finalY)
term.setCursorPos(finalX,finalY+self.yLength+1)
term.setTextColor(self.labelFg)
term.setBackgroundColor(self.labelBg)
term.write(self.label)
--[[print("hi")
print(layoutX)
print(layoutY)]]--
end
--Event handler function--
eventHandler = function(self)
while true do
local event, p1, p2, p3, p4, p5, p6 = os.pullEvent()
if event == "mouse_click" then
for i,v in pairs(self.Button) do
if v.finalX <= p2 and p2 <= v.finalX + v.xLength-1 and v.finalY <= p3 and p3 <= v.finalY + v.yLength-1 then
return {"Button",tostring(v.returnValue)}
end
end
for i,v in pairs(self.Toggle) do
if v.finalX <= p2 and p2 <= v.finalX + 3 and v.finalY == p3 then
return {"Toggle",tostring(v.returnValue)}
end
end
for i,v in pairs(self.BetterPaint) do
if v.finalX <= p2 and
p2 <= v.finalX + v.xLength-1 and
v.finalY <= p3 and p3 <= v.finalY + v.yLength-1 then
return {"Button",tostring(v.returnValue)}
end
end
term.setCursorPos(1,1)
print(self.xPos)
print(self.yPos)
os.pullEvent()
if self.nilClick then
if not (self.xPos <= p2 and p2 <= self.xLength and self.yPos <= p3 and p3 <= self.yLength) then
return {"Nil","Nil"}
end
end
elseif event == "key" then
--elseif event == "monitor_touch" then
--os.queueEvent("mouse_click", p1, p2, p3, p4, p5, p6)
end
end
end
--Load Function--
function Initialize()
local toReturn = {}
toReturn.Button = Button
toReturn.Layout = Layout
toReturn.Toggle = Toggle
toReturn.BackgroundColor = BackgroundColor
toReturn.ColorField = ColorField
toReturn.BetterPaint = BetterPaint
toReturn.eventHandler = eventHandler
return toReturn
end
Before you ask, all the apis have been initialized. If you don't believe me, check out this GitHub repo.
Thanks in advance and have a great afternoon (bulgarian time)
~Creator
PS: Line 330 is in the BetterPiant class section ;)/> BetterPaint is awesome!
This line:
local finalX = self.xPos + layoutX + addX - 1
In the BetterPaint.draw() function.
Edited on 15 March 2015 - 03:15 PM