This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
jag's profile picture

Display Api - Now Supports Special Characters!

Started by jag, 19 November 2013 - 01:52 PM
jag #1
Posted 19 November 2013 - 02:52 PM
Display API

By Kalle, a.k.a. jag.
I am now officially releasing my display API to the CC community; if you got any questions just ask them in the comment section below. Don’t hesitate!


Get it here
The file is uploaded to pastebin, you know the drill; just paste this in your in-game computer:

pastebin get VUvESDHi display
Direct link: http://pastebin.com/VUvESDHi
Raw code: http://pastebin.com/raw.php?i=VUvESDHi

FAQ
SpoilerWhat is it good for?
The display API is a simple way to make a GUI with a lot of utility functions!
What’s special about it?
First off it adds an easy to use read function with åäö support! It also removes the flickering that occurs when you constantly clear the screen. With ease you have a design without flickering and new "revolutionary" technology!
How do I use it?
Just head to the Usage section where you will find a list of all the functions available on the latest release, as well as the arguments required for each function!
I got an unlisted question?
As said, don’t hesitate, just ask in the comment section and if the question is good it will most certainly get added here!

Usage
Note: Use a colon instead of dot when calling a function via your class.
Ex: class:rect() instead of class.rect()
SpoilerRequired
Spoiler# To load the API
os.loadAPI("display")

# To create an object
class,time = display.load(path)
# Where path can be the path to a monitor.
# To use the standard terminal just leave blank.
# Returns
- class (table) = your object you will use, same way fs.open does it
- time (number) = the time it took to load in seconds
# Example:
class = display.load()
class = display.load("monitor_2")
class = display.load("left")

# Update the pixels
time = class:update()
# This function adds missing pixels and removes pixels outside the screen.
# Returns
- time (number) = the time it took to update in seconds
# Example:
class:update()

# Draw the pixels
time = class:draw()
# This function draws all pixels onto the objects screen.
# Returns
- time (number) = the time it took to draw in seconds
# Example:
class:draw()

Coloring
Spoiler# Set colors
class:setcolor(fg,bg)
class:setcolour(fg,bg)

class:setfgcolor(fg)
class:setfgcolour(fg)

class:setbgcolor(bg)
class:setbgcolour(bg)
# Sets the foreground/text and background color.
# If one of the arguments is missing, it will be ignored.
# Arguments
- fg (number) = foreground/text color
- bg (number) = background color
# Example:
class:setcolor(colors.white,colors.black)
class:setcolor(1,32768)

# Get colors
fg,bg = class:getcolor()
fg,bg = class:getcolour()

fg = class:getfgcolor()
fg = class:getfgcolour()

bg = class:getbgcolor()
bg = class:getbgcolour()
# Returns the color currently set.
# Returns
- fg (number) = foreground/text color
- bg (number) = background color
# Example:
class:setfgcolor(colors.lightBlue)
print( class:getfgcolor() )
>> 8

Stroke
Note: Stroke only changes drawing where the mode is set to "line"
Spoiler# Set stroke
class:setstroke(value)
# Sets the stroke to the specified value.
# Arguments
- value (number) = stroke size in CC "pixles"
# Example:
class:setstroke(value)

# Get stroke
value = class:getstroke()
# Gets the current stroke value
# Returns
- value (number) = current stroke size set
# Example:
class:setstroke(2)
print( class:getstroke() )
>> 2

Drawing
Note: The changes you make will only get visible when you run the class:draw() function!
Spoiler# Clear the screen
class:clear(ignorefg,ignorebg)
# Replaces the entire
# Arguments
- ignorefg (boolean) = only replace background, ignore text
- ignorebg (boolean) = only remove text, ignore background
# Example:
class:setbgcolor(colors.black)
class:clear(true)
>> text intact, background is black

# Write text
class:write(text,x,y,ignorebg)
# Writes out a string at a specified location.
# x,y defines the position to start writing, i.e. the far left of the text
# Does not have word wrap!
# Arguments
- text (string) = string to write out, does support special characters such as åäö
- x (number) = position on the x axis
- y (number) = position on the y axis
- ignorebg (boolean) = only remove text, ignore background
# Example:
class:setcolor(colors.white,colors.black)
class:write("Hello world!",2,3,false)
>> writes "Hello world!" at position x2 y3

# Draw a straight line
class:line(x1,y1,x2,y2,ignorefg)
# Draws a line between 2 points on the screen.
# Arguments
- x1 (number) = x position of the first point
- y1 (number) = y position of the first point
- x2 (number) = x position of the second point
- x2 (number) = y position of the second point
- ignorefg (boolean) = only replace background, ignore text
# Example:
class:setbgcolor(colors.blue)
class:line(1,1,4,4,false)
>> #___
>> _#__
>> __#_
>> ___#

# Draw a rectangle
class:rect(mode,x1,y1,x2,y2,ignorefg)
# Draws a rectangle in the area specified.
# Area is marked with 2 points.
# Available modes: fill, line.
# Arguments
- mode (string) = draw mode
- x1 (number) = x position of the first point
- y1 (number) = y position of the first point
- x2 (number) = x position of the second point
- x2 (number) = y position of the second point
- ignorefg (boolean) = only replace background, ignore text
# Example:
class:setbgcolor(colors.orange)
class:rect("fill",1,1,4,4,false)
>> ####
>> ####
>> ####
>> ####
class:setbgcolor(colors.magenta)
class:setstroke(1)
class:rect("line",1,1,4,4,false)
>> ####
>> #__#
>> #__#
>> ####

# Draw circle
class:circle(mode,x,y,r,ignorefg)
# Draws a circle with the xy position as the center.
# Because the pixels are taller then wide the circle becomes oval shaped.
# Available modes: fill, line.
# Arguments
- mode (string) = draw mode
- x (number) = center of the circle on the x axis
- y (number) = center of the circle on the y axis
- r (number) = radius of circle
- ignorefg (boolean) = only replace background, ignore text
# Example:
class:setbgcolor(colors.brown)
class:circle("fill",3,3,2,false)
>> __#__
>> _###_
>> #####
>> _###_
>> __#__
class:setbgcolor(colors.cyan)
class:setstroke(1)
class:circle("line",3,3,2.5,false)
>> _###_
>> #___#
>> #___#
>> #___#
>> _###_

Utilities
Spoiler# Read
text = class:read(x,y,w,len,initstr,char,ingorebg,callback)
# Creates a text field.
# Supports special characters such as åäö!
# Note: Works as a loop, includes an update and draw function!
# Arguments
- x (number) = position on the x axis
- y (number) = position on the y axis
- w (number) = width of text field
- len (number) = max length of text
- initstr (string) = initial string, text is set to this at start
- char (string) = the input is viewed as this, repeats
- ignorebg (boolean) = only remove text, ignore background
- callback (function) = events passes trough here, if returns true it ends the read funciton
# Returns
- text (string) = string that was entered
# Example:
class:setcolor(colors.white,colors.black)
text = class:read(1,1,15,"Hello world!",_,false,_)
>> Hello world!___
# Default callback:
callback = function(ev,p1,p2,p3,p4,p5)
	if ev == "key" and p1 == keys.enter then
		return true
	end
end

To-do
Spoiler

# Add a "draw polygon" function
# Get better visuals on examples in the usage tab

Known bugs/glitches
Spoiler

# Invalid argument on the majority of functions will give non-user friendly errors
# If you disconnect a monitor while in usage it crashes.

Example programs
Spoiler
Circle program
Spoiler
os.loadAPI("display")
local class = display.load()

local w,h = class.obj.getSize()

class:setbgcolor(colors.lightBlue)
class:rect("fill",2,2,w-1,h-1)

class:setfgcolor(colors.orange)
class:write("Press Q to quit",1,1)

while true do
	class:update()
	class:draw()

	local ev,p1,p2,p3,p4,p5 = os.pullEvent()

	if ev == "key" and p1 == keys.q then
		break
	elseif ev == class.eventname then
		local size = math.random(1,10)
		local stroke = math.random(1,5)
		local color = 2^math.random(1,15)
		class:setbgcolor(color)
		class:setstroke(stroke)
		class:circle("line",p2,p3,size,true)
	end
end
Input program
Spoiler


os.loadAPI("displayAPI/display")
local class = display.load()

local username = ""
local email = ""

class:setstroke(1)
class:setbgcolor(colors.lightBlue)
class:rect("fill",2,2,50,18,true)

class:setfgcolor(colors.blue)
class:write("Username:",5,9,true)
class:write("E-mail:",5,11,true)

local callback = function(ev,p1,p2,p3,p4,p5)
	if ev == "key" then
		if p1 == keys.enter
		or p1 == keys.tab then
			return true
		end
	end
end

local function shorten(str,max,char)
	char = char or ""
	if str:len() > max then
		str = str:sub(1,max-char:len()) .. char
	end
	return str
end

local function redraw()
	class:rect("fill",15,9,45,9,false)
	class:rect("fill",13,11,45,11,false)
	local short = ".."
	class:write(shorten(username,31,short),15,9)
	class:write(shorten(email,33,short),13,11)
end

class:setcolor(colors.white,colors.black)
while true do
	redraw()
	username = class:read(15,9,30,_,username,_,false,callback)
	redraw()
	email = class:read(13,11,32,_,email,_,false,callback)
end
Edited on 19 November 2013 - 02:29 PM
theoriginalbit #2
Posted 19 November 2013 - 09:20 PM
Usage
Note: Use a colon instead of dot when calling a function via your class.
Ex: class:rect() instead of class.rect()
You can fix that you know. Make it work either way.
jag #3
Posted 20 November 2013 - 12:02 AM
You can fix that you know. Make it work either way.
Maybe some complicated way I don't know of, but from my research; no you cant, not in this senario.

Please give an example on how to fix such a thing.
This is how the class system is done in the API:

function setcolor(class,fg,bg)
    class.fgcolor = fg or class.fgcolor
    class.bgcolor = bg or class.bgcolor
end

function load()
    local class = {}
    class.fgcolor = colors.white
    class.bgcolor = colors.black
    class.setcolor = setcolor
    return class
end
Now is there an alternative way to access the class without the extra argument? No.
Edited on 19 November 2013 - 11:04 PM
theoriginalbit #4
Posted 20 November 2013 - 01:39 AM
Now is there an alternative way to access the class without the extra argument? No.
Of course there is… There are two methods around it, you can make another function to "clean" arguments, or you can go a slightly more complicated route with metatables. Symmetric and I have been discussing these methods over the past few days/weeks.
AgentE382 #5
Posted 20 November 2013 - 02:04 AM
Ahem…. Listen to Bit. One method is as follows:
function setcolor(class,fg,bg)
    class.fgcolor = fg or class.fgcolor
    class.bgcolor = bg or class.bgcolor
end

function load()
    local class = {}
    class.fgcolor = colors.white
    class.bgcolor = colors.black
    class.setcolor = function(...) setcolor(class, select(-2, ...)) end
    return class
end
Edited on 20 November 2013 - 01:26 AM
theoriginalbit #6
Posted 20 November 2013 - 02:13 AM
-snip-
Well there is a 3rd method… xD

This is the method that symmetric made during my discussions with him. I've gone ahead and added it to your use case, commented all of it, and added an example so you can see that it works. Pastebin link.
Edited on 20 November 2013 - 01:14 AM
jag #7
Posted 20 November 2013 - 10:55 AM
Well who cares, (good reply from you guys btw, but) it dosent matter it'll do fine without it. Now my key component is the read() function which supports special characters, have you taken a look at that yet?
karelmikie3 #8
Posted 22 November 2013 - 02:31 PM
great work :D/> :3