Posted 20 March 2013 - 08:57 PM
[Lua][Error] Problem with classes and gui
Hello everyone!
I'm writing simple API to draw and manage UI in advanced monitors. Everything was nice till I run nearly "release" version of API in simple test program.
I'm new to lua so I did what I can to try to solve this by myself. I think the problem is in case on using some kind of classes, but I don't know what's wrong.
Every time when I run program I get only debug message and error:
Now the source code.
Program:
monitorXAPI:
textXAPI
What can I do to make it work? Where is my mistake?
Hello everyone!
I'm writing simple API to draw and manage UI in advanced monitors. Everything was nice till I run nearly "release" version of API in simple test program.
I'm new to lua so I did what I can to try to solve this by myself. I think the problem is in case on using some kind of classes, but I don't know what's wrong.
Every time when I run program I get only debug message and error:
--DRAWING--
monitorXAPI:211: attempt to index ? (a nil value)
Now the source code.
Program:
Spoiler
os.loadAPI("textXAPI")
os.loadAPI("monitorXAPI")
btnFill = colors.lightGray
btnText = colors.black
btnDisFill = colors.gray
btnDisText = colors.black
mainPage = {}
mainPage[1] = monitorXAPI.StatusBar:new
{ pathLength = 54,
timeLength = 25,
path = "path",
pathFillColor = colors.gray,
pathTextColor = colors.white,
timeFillColor = colors.lightGray,
timeTextColor = colors.black
}
mainPage[2] = monitorXAPI.Button:new
{ x = 2,
y = 3,
size = 2,
length = 25,
text = "Touch to set path",
enabled = true,
visible = true,
enabledFillColor = colors.black,
enabledTextColor = colors.lightGray,
disabledFillColor = colors.black,
disabledTextColor = colors.gray,
onclickFunction = function() mainPage[1].path = "Zmieniono tytul!" end
}
monitorXAPI.monitorSetup("right", 0.5, colors.black)
monitorXAPI.uiEvents(mainPage, 1)
monitorXAPI:
Spoiler
-----------------
-- monitorXAPI --
-- by Xkonti --
-----------------
---- External APIs ----
-- You have to include:
-- - textXAPI
-----------------------
-------------------
-- GLOBAL VARIABLES
local XApiMonitor -- peripheral
local XApiBkgColor -- default color for screen cleaning
--
-------------------
--
------ Utilities ------
--
function monitorSetup(side, textScale, backgroundColor)
XApiMonitor = peripheral.wrap(side)
XApiMonitor.setTextScale = textScale
XApiBkgColor = backgroundColor
clear(XApiBkgColor)
end
-- Clear screen
function clear(color)
XApiMonitor.setBackgroundColor(color)
XApiMonitor.clear()
end
--
------ Text ------
--
-- Draw text
function drawText(x, y, text, bkgColor, txtColor)
XApiMonitor.setBackgroundColor(bkgColor)
XApiMonitor.setTextColor(txtColor)
XApiMonitor.setCursorPos(x, y)
XApiMonitor.write(text)
end
-- Draw centered text
function drawCenteredText(x, y, text, length, backgroundColor, textColor)
drawText(x + textXAPI.offsetToCenter(text, length), y, text, backgroundColor, textColor)
end
-- Draw right-aligned text
function drawRightAlignedText(x, y, text, length, backgroundColor, textColor)
drawText(x + textXAPI.offsetToRight(text, length), y, text, backgroundColor, textColor)
end
--
------ Shapes ------
--
-- Colored Filled Rectangle with Stroke
function drawCFRectangle(x1, y1, x2, y2, strokeColor, fillColor)
XApiMonitor.setBackgroundColor(strokeColor)
local x, y
-- Top line
XApiMonitor.setCursorPos(x1, y1)
for x=x1, x2, 1 do
XApiMonitor.write(" ")
end
-- Bottom line
XApiMonitor.setCursorPos(x1, y2)
for x=x1, x2, 1 do
XApiMonitor.write(" ")
end
-- Left line
for y=y1+1, y2-1, 1 do
XApiMonitor.setCursorPos(x1, y)
XApiMonitor.write(" ")
end
-- Right line
for y=y1+1, y2-1, 1 do
XApiMonitor.setCursorPos(x2, y)
XApiMonitor.write(" ")
end
drawCSRectangle(x1+1, y1+1, x2-1, y2-1, fillColor)
end
-- Colored Solid Rectangle
function drawCSRectangle(x1, y1, x2, y2, color)
XApiMonitor.setBackgroundColor(color)
local x, y
for y=y1, y2, 1 do
monitor.setCursorPos(x1, y)
for x=x1, x2, 1 do
monitor.write(" ")
end
end
end
-- Draw edit box
function drawEditBox(x, y, size, length, text, strokeColor, fillColor, textColor)
drawCFRectangle(x, y, x+length+(2*size), y+(2*size), strokeColor, fillColor)
drawText(x+size, y+size, text, fillColor, textColor)
end
-- Draw button
function drawButton(x, y, size, length, text, fillColor, textColor)
drawCSRectangle(x, y, x+length+(2*size), y+(2*size), fillColor)
drawCenteredText(x+size, y+size, text, length, fillColor, textColor)
end
-- Draw statusbar
function drawStatusBar(pathLength, timeLength, path, pathFillColor, pathTextColor, timeFillColor, timeTextColor)
drawCSRectangle(1, 1, pathLength, 1, pathFillColor)
drawCSRectangle(pathLength + 1, 1, pathLength + timeLength, 1, timeFillColor)
drawText(1,1, path, pathFillColor, pathTextColor)
timeHour = textutils.formatTime(os.time(), true)
timeDay = tostring(os.day())
drawRightAlignedText(pathLength + 1, 1, timeHour.." of "..timeDay.." MC day", timeLength, timeFillColor, timeTextColor)
end
--
------ Classes ------
--
-----------------------
--- StatusBar class ---
-- StatusBar declaration
StatusBar = { pathLength = 54,
timeLength = 25,
path = "path",
pathFillColor = colors.gray,
pathTextColor = colors.white,
timeFillColor = colors.lightGray,
timeTextColor = colors.black
}
-- Constructor
function StatusBar:new(object)
object = object or { pathLength = 54,
timeLength = 25,
path = "path",
pathFillColor = colors.gray,
pathTextColor = colors.white,
timeFillColor = colors.lightGray,
timeTextColor = colors.black
}
setmetatable(object, self)
self.__index = self
return object
end
-- StatusBar draw function
function StatusBar:draw()
drawStatusBar(self.pathLength, self.timeLength, self.path, self.pathFillColor, self.pathTextColor, self.timeFillColor, self.timeTextColor)
end
-- StatusBar touch function
function StatusBar:touch()
end
--------------------
--- Button class ---
-- Button declaration
Button = { x = 1,
y = 1,
size = 1,
length = 5,
text = "text",
enabled = true,
visible = true,
enabledFillColor = colors.lightGray,
enabledTextColor = colors.black,
disabledFillColor = colors.gray,
disabledTextColor = colors.black,
onClickFunction = function() end
}
-- Constructor
function Button:new(object)
object = object or { x = 1,
y = 1,
size = 1,
length = 5,
text = "text",
enabled = true,
visible = true,
enabledFillColor = colors.black,
enabledTextColor = colors.lightGray,
disabledFillColor = colors.black,
disabledTextColor = colors.gray,
onclickFunction = function() end
}
setmetatable(object, self)
self.__index = self
return object
end
-- Button draw function
function Button:draw()
if self.visible then
if self.enabled then
drawButton(self.x, self.y, self.size, self.length, self.text, self.enabledFillColor, self.enabledTextColor)
else
drawButton(self.x, self.y, self.size, self.length, self.text, self.disabledFillColor, self.disabledTextColor)
end
end
end
-- When clicked function - checks if button was clicked and starts onClickFunction - returns true or false
function Button:touch(x, y)
if self.enabled then
if x >= self.x then
if x <= (self.x + self.length + (2 * self.size)) then
if y >= self.y then
if y <= (self.y + (2 * self.size)) then
self.onClickFunction()
return true
else
return false
end
else
return false
end
else
return false
end
else
return false
end
else
return false
end
end
-- Set Button position
function Button:setPos(x, y)
self.x = x
self.y = y
end
--
------ UI functions ------
--
function uiDraw(components)
print("--DRAWING--") -- debug
for i=1, table.maxn(components) do
components[i].draw()
end
end
-- Event handling
function uiEvents(components, refreshRate)
os.startTimer(refreshRate) -- Start refreshing screen
while true do
local event, param1, param2, param3 = os.pullEvent() -- event handler
if event == "timer" then -- time to refresh?
os.startTimer(refreshRate) -- start new timer
uiDraw(components) -- refresh UI
elseif event == "monitor_touch" then -- touched?
uiTouch(components, param2, param3) -- check what was touched
end
end
end
-- Check what was clicked
function uiTouch(components, x, y)
print("--TOUCHING--") -- debug
for i=1, table.maxn(components) do
if components[i].touch(x, y) then
break
end
end
end
textXAPI
Spoiler
-----------------
-- textXAPI --
-- by Xkonti --
-----------------
function offsetToCenter(text, length)
local offset
offset = math.floor( (length - string.len(text) ) / 2)
return offset
end
function offsetToRight(text, length)
local offset = math.floor( length - string.len(text) )
return offset
end
What can I do to make it work? Where is my mistake?