I'm here to introduce my new button API.

I know there are a lot of button APIs already out there, some better than the others. But I thought I would give it a shot as well.
This API has the ability to easily create buttons on a monitor. However instead of most APIs having to set the coordinates of the button in exact numbers. You can with this API use relative positions. So you won't have to go through trial and error to get multiple buttons well alligned, or a button alligned in the middle. This is now easily doable by using numbers between 0 and 1.

The code of the API:
Spoiler

local idleColor=256
local activatedColor=8192
local backgroundColor=32768
local textColor=1
local buttons={}
local monitor=nil
local debugMode=false
local monitorSide=nil

function addButton(x,y,width,height,text,toRunFunction,toggle,relative,idleColor,activeColor,textColor)
if monitor==nil then
if debugMode==true then
print("Monitor is not yet defined! Use setMonitorSide(side)")
end
return false,"Monitor is not yet defined! Use setMonitorSide(side)"
elseif x==nil or y==nil or width==nil or height==nil or text==nil then
if debugMode==true then
print("Not all required arguments are specified.")
end
return false,"Not all required arguments are specified."
else
buttonID=#buttons+1
if string.len(text)>width and relative~=true then
text=string.sub(text,0,width)
elseif string.len(text)>width*screenx then
text=string.sub(text,0,width*screenx)
end
buttons[buttonID]={['x']=x,['y']=y,['width']=width,['height']=height,['text']=text,['active']=false,['function']=toRunFunction,['toggle']=toggle,['relative']=relative,['activeColor']=activeColor,['idleColor']=idleColor,['textColor']=textColor}
drawAllButtons{}
return buttonID
end
end

function removeButton(buttonID)
if monitor==nil then
if debugMode==true then
print("Monitor is not yet defined! Use setMonitorSide(side)")
end
return false,"Monitor is not yet defined! Use setMonitorSide(side)"
else
if buttonID==nil then
if debugMode==true then
print("Not all required arguments are specified.")
end
return false,"Not all required arguments are specified."
else
if buttons[buttonID]==nil then
if debugMode==true then
print("That button ID does not correspond with a button!")
end
return false,"That button ID does not correspond with a button!"
else
buttons[buttonID]={"Removed"}
end
end
end
end


function drawAllButtons()
if monitor==nil then
if debugMode==true then
print("Monitor is not yet defined! Use setMonitorSide(side)")
end
return false,"Monitor is not yet defined! Use setMonitorSide(side)"
else
monitor.setBackgroundColor(backgroundColor)
monitor.clear()
for buttonID,buttonInfo in pairs(buttons) do
local x=buttonInfo['x']
local y=buttonInfo['y']
local width=buttonInfo['width']
local height=buttonInfo['height']
if buttonInfo['relative']==true then
x=math.floor(x*screenx+0.5)
y=math.floor(y*screeny+0.5)
width=math.floor(width*screenx+0.5)
height=math.floor(height*screeny+0.5)
end
monitor.setCursorPos(x,y)
if buttonInfo['active']==true then
if buttonInfo['activeColor']==nil then
monitor.setBackgroundColor(activatedColor)
else
monitor.setBackgroundColor(buttonInfo['activeColor'])
end
else
if buttonInfo['idleColor']==nil then
monitor.setBackgroundColor(idleColor)
else
monitor.setBackgroundColor(buttonInfo['idleColor'])
end
end
for i=0,height-1 do
monitor.setCursorPos(x,y+i)
for i=1,width do
monitor.write(" ")
end
end
if buttonInfo['textColor']==nil then
monitor.setTextColor(textColor)
else
monitor.setTextColor(buttonInfo['textColor'])
end
stringX=x+(width/2-string.len(buttonInfo['text'])/2)
stringY=y+(math.floor(height)/2)
monitor.setCursorPos(stringX,stringY)
monitor.write(buttonInfo['text'])
end
end
end

function getButtonInfo(buttonID)
if monitor==nil then
if debugMode==true then
print("Monitor is not yet defined! Use setMonitorSide(side)")
end
return false,"Monitor is not yet defined! Use setMonitorSide(side)"
else
if buttonID==nil then
if debugMode==true then
print("Not all required arguments are specified.")
end
return false,"Not all required arguments are specified."
else
if buttons[buttonID]==nil then
if debugMode==true then
print("That button ID does not correspond with a button!")
end
return false,"That button ID does not correspond with a button!"
else
if debugMode==true then
for infoID,info in pairs(buttons[buttonID]) do
if type(info)=="boolean" then
if info==false then
info="false"
else
info="true"
end
elseif type(info)=="function" then
info="function"
end
print(infoID.." :"..info)

end
end
return buttons[buttonID]
end
end
end
end

function setButtonInfo(buttonID,infoID,info)
if monitor==nil then
if debugMode==true then
print("Monitor is not yet defined! Use setMonitorSide(side)")
end
return false,"Monitor is not yet defined! Use setMonitorSide(side)"
else
if buttonID==nil then
if debugMode==true then
print("Not all required arguments are specified.")
end
return false,"Not all required arguments are specified."
else
if buttons[buttonID]==nil then
if debugMode==true then
print("That button ID does not correspond with a button!")
end
return false,"That button ID does not correspond with a button!"
else
buttons[buttonID][infoID]=info
end
end
end
end

function run()
event,side,clickX,clickY=os.pullEvent()
if event=="monitor_touch" then
for buttonID,buttonInfo in pairs(buttons) do
local x=buttonInfo['x']
local y=buttonInfo['y']
local width=buttonInfo['width']
local height=buttonInfo['height']
if buttonInfo['relative']==true then
x=math.floor(x*screenx+0.5)
y=math.floor(y*screeny+0.5)
width=math.floor(width*screenx+0.5)
height=math.floor(height*screeny+0.5)
end
if debugMode==true then
print("Pos:"..x..","..y)
end
if clickX>x and clickX<x+width and clickY>y and clickY<y+height then
if debugMode==true then
print("Clicked :"..buttonID)
end
if buttonInfo['toggle']==true then
buttonInfo['active']=not buttonInfo['active']
if buttonInfo['active']==true then
buttonInfo['function'](true)
else
buttonInfo['function'](false)
end
drawAllButtons()
else
buttonInfo['function']()
buttonInfo['active']=true
drawAllButtons()
sleep(0.5)
if buttonInfo~=nil then
buttonInfo['active']=false
end
drawAllButtons()
end

end
end
elseif event=="monitor_resize" then
if side==monitorSide then
setMonitorSide(side)
drawAllButtons()
end
end
end

--[[
function updateButtonPositions()
for buttonID,buttonInfo in pairs(buttons) do
if buttonInfo['relative']==true then
x=
y=
width=
height=
x=math.floor(x*screenx+0.5)
y=math.floor(y*screeny+0.5)
width=math.floor(width*screenx+0.5)
height=math.floor(height*screeny+0.5)
end
end
end
]]

function setMonitorSide(side)
if side==nil then
if debugMode==true then
print("Not all required arguments are specified.")
end
return false,"Not all required arguments are specified."
else
monitor=peripheral.wrap(side)
screenx,screeny=monitor.getSize()
monitorSide=side
end
end

function setDebugMode(bool)
if bool==nil then
if debugMode==true then
print("Not all required arguments are specified.")
end
return false,"Not all required arguments are specified."
else
debugMode=bool
end
end

function setIdleColor(color)
if color==nil then
if debugMode==true then
print("Not all required arguments are specified.")
end
return false,"Not all required arguments are specified."
else
idleColor=color
drawAllButtons()
end
end

function setActiveColor(color)
if color==nil then
if debugMode==true then
print("Not all required arguments are specified.")
end
return false,"Not all required arguments are specified."
else
activatedColor=color
drawAllButtons()
end
end

function setBackgroundColor(color)
if color==nil then
if debugMode==true then
print("Not all required arguments are specified.")
end
return false,"Not all required arguments are specified."
else
backgroundColor=color
drawAllButtons()
end
end

function setTextColor(color)
if color==nil then
if debugMode==true then
print("Not all required arguments are specified.")
end
return false,"Not all required arguments are specified."
else
textColor=color
drawAllButtons()
end
end

Pastebin link: http://pastebin.com/Hfkga8c8

Function documentation:
Word file
Pastebin
Text:
SpoilersetMonitorSide(side)
Sets the side the monitor is on. This is required before calling any of the other functions
Required arguments:
Side Side the monitor is on. (string)
Optional arguments:
N/A
Returns
N/A



addButton(x,y,width,height,text,function,toggle,relative,idleColor,activeColor,textColor)
This functions adds a button to the monitor
Required arguments:
X The x position of the left top corner of the button. (float)
Y The y position of the left top corner of the button. (float)
Width The width of the button. (float)
Height The height of the button. (float)
Text The text you want to be displayed on the button. (string)
Function The function you want to call when the button is clicked. (function)
Optional arguments:
Toggle If this is set to true the button will be toggled when clicked (Boolean)
[indent=1.75]Relative If this is set to true the x,y,width and height variable will be made relative to the screen size. Meaning an x of 0.2 would set the button at 0.2 of the entire screen width. (Boolean)[/indent]
IdleColor The color of the button when not activated. (color) (Will use default when not specified)
ActiveColor The color of the button when activated. (color) (Will use default when not specified)
TextColor The color of the text on the button. (color) (Will use default when not specified)

Returns
The function returns a button id (float)
The function returns false when not all arguments were specified, or no monitor was assigned.
removeButton(buttonID)
This function removes a button from the monitor
Required arguments:
buttonID The ID of the button (float)
Optional arguments:
N/A
Returns
Returns true when successfully removed.
Returns false when not successfully removed.


getButtonInfo(buttonID)
Required arguments:
buttonID The ID of the button (float)
Optional arguments:
N/A
Returns
Returns a table of all information about that button. Prints this when in debug mode.
Returns false when not successful.


setButtonInfo(buttonID,infoID,info)
This function sets info on buttons, what info there is available can be found by using getButtonInfo()
Required arguments:
buttonID The ID of the button (float)
infoID The key that the info is saved on. (string)
info The info to be set to (any)
Optional arguments:
N/A
Returns
Returns true when sucessful
Returns false when not successful
run ()
This function checks for clicks on the screen, and runs the function respectable to that button.
Required arguments:
N/A
Optional arguments:
N/A
Returns
N/A






setDebugMode(bool)
Sets whether debug mode is activated, if it is activated it will print errors.
Required arguments:
Bool true to activate debug mode, false to deactivate. (Boolean)
Optional arguments:
Returns


setIdleColor (color)
Required arguments:
Color color for the idle background of the button (color)
Optional arguments:
N/A
Returns
N/A



setActiveColor(color)
Required arguments:
Color color for the active background of the button (color)
Optional arguments:
N/A
Returns
N/A



setBackgroundColor(color)
Required arguments:
Color color for the idle background of the monitor (color)
Optional arguments:
N/A
Returns
N/A



setTextColor(color)
Required arguments:
Color color for the text of the button (color)
Optional arguments:
N/A
Returns
N/A


Extra information:
SpoilerButton Presses:

SpoilerWhen a button is pressed the function that is called from that button will be called with the buttonID of the pressed button as first argument.

Relative:
SpoilerWhen relative is set to true the x,y,width and height value will all be relative to the screen.
Example:

relativeButton=button.addButton(0.3,0.4,0.4,0.1,"text",function() print("hi") end,false,true)
This button will be put at three tenth of the screen on the x axis. Being a a little left from the middle, this way the button can be aligned in the middle of the screen very easily (or aligned elsewhere)

Toggle:

SpoilerThere is an option when creating a button for it to be a 'toggle' button. When this is set to true the state of the button will change once when pressed. The function called from this will then be called with 2 variables, the first being buttonID, the other being the state of the toggle button. True when activated false when deactivated.



Resizing:

SpoilerWhen the monitor gets resized the buttons will automaticly update (including relative positions)

Colors:

SpoilerWhen setting a color you can use anything from the color API: http://computercraft...olors_%28API%29

Errors:

SpoilerWhen a function returns false it will allways return a second argument being an error message. For example:

button,error=createButton(1,1,1,1)
print(error)
That will print a message saying you have not specified all required arguments, all functions have this built into them.

Debug mode:

SpoilerDebug mode automaticly prints error messages, and even some more information, if in debug mode getButtonInfo() will also be printed.

Don't forget to load the api first, do this by doing os.loadAPI(fileName)
(The fileName is the name you downloaded the API from using pastebin)

Example code:
Spoiler

function test()
print("debug")
end
os.loadAPI("button")
button.setDebugMode(true)
button.setMonitorSide("right")
button.addButton(2,2,7,3,"precise",test)
relativeTest=button.addButton(0.4,0.4,0.2,0.2,"relative",test,false,true)
toggleTest=button.addButton(0.4,0.65,0.2,0.1,"toggle",test,true,true)
button.getButtonInfo(relativeTest)
while true do
  button.run()
end

Screenshots:
Spoiler

Known bugs:
None at this moment.