View difference between Paste ID: VxdRfhTc and YeYhXftV
SHOW: | | - or go back to the newest paste.
1
-- display API 
2
-- made by akaJag
3
-- work in progress
4
5
function round(num)
6
	if type(num) ~= "number" then return num end
7
	if num%1<.5 then num=math.floor(num) end
8
	if num%1>=.5 then num=math.ceil(num) end
9
	return num
10
end
11
12
function setupdaterate(class,s)
13
	class.updaterate = s
14
end
15
16
function getupdaterate(class)
17
	return class.updaterate
18
end
19
20
function removepixles(class)
21
	local w,h = class.obj.getSize()
22
	
23
	-- check row
24
	local width = next(class.pixles)
25
	while width do
26
		if width > w or width < 0 then
27
			-- remove row
28
			local tmpw = width
29
			width = next(class.pixles,width)
30
			class.pixles[tmpw] = nil
31
		else
32
			-- check column
33
			local height = next(class.pixles[width])
34
			while height do
35
				if height > h or height < 0 then
36
					-- remove column
37
					local tmph = height
38
					height = next(class.pixles[width],height)
39
					class.pixles[width][tmph] = nil
40
				else
41
					-- next iteration
42
					height = next(class.pixles[width],height)
43
				end
44
			end
45
			-- next iteration
46
			width = next(class.pixles,width)
47
		end
48
	end
49
end
50
51
function fixpixles(class)
52
	local w,h = class.obj.getSize()
53
	for width = 1,w do
54
		if class.pixles[width] == nil then class.pixles[width] = {} end
55
		for height = 1,h do
56
			if class.pixles[width][height] == nil then
57
				class.pixles[width][height] = {sym=" ",bg=colors.black,fg=colors.white}
58
			end
59
		end
60
	end
61
end
62
63
-- returns:
64
--	(number) update time
65
function update(class)
66
	local startupdate = os.clock()
67
	
68
	class:removepixles()
69
	class:fixpixles()
70
	
71
	local endupdate = os.clock()
72
	return endupdate - startupdate
73
end
74
75
function draw(class)
76
	local startdraw = os.clock()
77
	
78
	for w in pairs(class.pixles) do
79
		for h,pixle in pairs(class.pixles[w]) do
80
			class.obj.setCursorPos(w,h)
81
			class.obj.setBackgroundColor(pixle.bg or colors.black)
82
			class.obj.setTextColor(pixle.fg or colors.white)
83
			class.obj.write(pixle.sym or " ")
84
		end
85
	end
86
	
87
	local enddraw = os.clock()
88
	return enddraw - startdraw
89
end
90
91
-- can be used in a parallel loop
92
-- dont forget to do prepareloop() before running
93
-- stop it with stoploop()
94
function loop(class)
95
	if not running then return end
96
	local s = class:update()
97
	s = s + class:draw()
98
	sleep(updaterate - s)
99
end
100
101
function prepareloop(class)
102
	class.looprunning = true
103
	class.looptime = os.clock()
104
end
105
106
-- returns the time the loop has been on
107
function stoploop()
108
	class.looprunning = false
109
	return os.clock - class.looptime
110
end
111
112
function setcolor(class,fg,bg)
113
	class.fgcolor = fg or class.fgcolor
114
	class.bgcolor = bg or class.bgcolor
115
end
116
117
function getcolor(class)
118
	return class.fgcolor,class.bgcolor
119
end
120
121
function setfgcolor(class,col)
122
	class.fgcolor = col
123
end
124
125
function getfgcolor(class)
126
	return class.fgcolor
127
end
128
129
function setbgcolor(class,col)
130
	class.bgcolor = col
131
end
132
133
function getbgcolor(class)
134
	return class.bgcolor
135
end
136
137
-- stroke is only used with "line" draw mode
138
function setstroke(class,var)
139
	class.stroke=var
140
end
141
142
function getstroke(class)
143
	return class.stroke
144
end
145
146
-- clears the entire screen
147
-- bg = only change background, ignore text
148
function clear(class,bg)
149
	for w in pairs(class.pixles) do
150
		for h,pixle in pairs(class.pixles[w]) do
151
			class.pixles[w][h].bg = class.bgcolor
152
			if bg ~= true then
153
				class.pixles[w][h].sym = " "
154
			end
155
		end
156
	end
157
end
158
159
-- trans = transparant option
160
function write(class,str,x,y,trans)
161
	x=round(x) y=round(y)
162
	for count = 1,#str do
163
		if class.pixles[x+count-1] then
164
			if class.pixles[x+count-1][y] then
165
				class.pixles[x+count-1][y].sym = str:sub(count,count)
166
				class.pixles[x+count-1][y].fg = class.fgcolor
167
				if trans ~= true then
168
					class.pixles[x+count-1][y].bg = class.bgcolor
169
				end
170
			end
171
		end
172
	end
173
end
174
175
function line(class,x1,y1,x2,y2,bg)
176
	-- Bresenham's algorithm
177
	local dx = x2 - x1
178
	if dx < 0 then dx = -dx end
179
	local dy = y2 - y1
180
	if dy < 0 then dy = -dy end
181
	
182
	local sx,sy
183
	if x1 < x2 then sx = 1
184
	else sx = -1 end
185
	if y1 < y2 then sy = 1
186
	else sy = -1 end
187
	
188
	local err = dx - dy
189
	
190
	repeat
191
		local x,y = round(x1),round(y1)
192
		if class.pixles[x] then
193
			if class.pixles[x][y] then
194
				class.pixles[x][y].bg = class.bgcolor
195
				if bg ~= true then
196
					class.pixles[x][y].sym = " "
197
				end
198
			end
199
		end
200
		
201
		if x1 == x2 and y1 == y2 then break end
202
		local e2 = 2*err
203
		if e2 > -dy then
204
			err = err - dy
205
			x1 = x1 + sx
206
		end
207
		if e2 < dx then
208
			err = err + dx
209
			y1 = y1 + sy
210
		end
211
	until false
212
end
213
214
-- supported modes: fill, line
215
-- bg = only set background color
216
function rect(class,mode,x1,y1,x2,y2,bg)
217
	x1=round(x1) y1=round(y1) x2=round(x2) y2=round(y2)
218
	if mode == "fill" then
219
		for x = x1,x2 do
220
			for y = y1,y2 do
221
				if class.pixles[x] ~= nil then
222
					if class.pixles[x][y] ~= nil then
223
						class.pixles[x][y].bg = class.bgcolor
224
						if bg ~= true then
225
							class.pixles[x][y].sym = " "
226
						end
227
					end
228
				end
229
			end
230
		end
231
	elseif mode == "line" then
232
		-- top line
233
		for x = x1,x2 do
234
			for y = y1,y1+class.stroke-1 do
235
				if class.pixles[x] ~= nil then
236
					if class.pixles[x][y] ~= nil then
237
						class.pixles[x][y].bg = class.bgcolor
238
						if bg ~= true then
239
							class.pixles[x][y].sym = " "
240
						end
241
					end
242
				end
243
			end
244
		end
245
		-- bottom line
246
		for x = x1,x2 do
247
			for y = y2-class.stroke+1,y2 do
248
				if class.pixles[x] ~= nil then
249
					if class.pixles[x][y] ~= nil then
250
						class.pixles[x][y].bg = class.bgcolor
251
						if bg ~= true then
252
							class.pixles[x][y].sym = " "
253
						end
254
					end
255
				end
256
			end
257
		end
258
		-- right line
259
		for x = x2-class.stroke+1,x2 do
260
			for y = y1,y2 do
261
				if class.pixles[x] ~= nil then
262
					if class.pixles [x][y] ~= nil then
263
						class.pixles[x][y].bg = class.bgcolor
264
						if bg ~= true then
265
							class.pixles[x][y].sym = " "
266
						end
267
					end
268
				end
269
			end
270
		end
271
		-- left line
272
		for x = x1,x1+class.stroke-1 do
273
			for y = y1,y2 do
274
				if class.pixles[x] ~= nil then
275
					if class.pixles [x][y] ~= nil then
276
						class.pixles[x][y].bg = class.bgcolor
277
						if bg ~= true then
278
							class.pixles[x][y].sym = " "
279
						end
280
					end
281
				end
282
			end
283
		end
284
	end
285
end
286
287
-- supported modes: fill, line
288
-- bg = only set background color
289
function circle(class,mode,x,y,r,bg)
290
	x=round(x) y=round(y)
291
	for w in pairs(class.pixles) do
292
		for h in pairs(class.pixles[w]) do
293
			-- pythagrias sats
294
			-- a^2 + b^2 = c^2
295
			local dis = math.sqrt((w-x)^2 + (h-y)^2)
296
			if dis <= r then
297
				if mode == "fill" or
298
				(mode == "line" and dis >= r-class.stroke) then
299
					if class.pixles[w] ~= nil then
300
						if class.pixles[w][h] ~= nil then
301
							class.pixles[w][h].bg = class.bgcolor
302
							if bg ~= true then
303
								class.pixles[w][h].sym = " "
304
							end
305
						end
306
					end
307
				end
308
			end
309
		end
310
	end
311
end
312
313
local function strtotbl(str)
314
	local tbl = {}
315
	for uchar in str:gmatch("([%z\1-\127\194-\244][\128-\191]*)") do
316
		table.insert(tbl,uchar)
317
	end
318
	return tbl
319
end
320
321
local function tbltostr(tbl)
322
	local str = ""
323
	for _,value in pairs(tbl) do
324-
	local text = initstr
324+
		str=str..tostring(value)
325-
	local padding = text:len()-w
325+
326-
	local cursor = text:len()
326+
327
328
-- x,y = top left corner of text field
329
-- w = width of text field
330
-- l = max lenght of text
331
-- c = make the text look like a certain character
332
-- trans = transparent
333
-- callback = function, gets events as parameters, if returns true then exit
334
function read(class,x,y,w,l,initstr,c,trans,callback)
335
	x=round(x) y=round(y) w=round(w) l=round(l)
336
	if type(l)~="number" then l=-1 end
337
	if type(initstr)~="string" then initstr="" end
338
	local running = true
339
	local text = initstr or ""
340
	local padding = #text-w
341
	local cursor = #text
342
	
343
	callback = callback or function(ev,p1,p2,p3,p4,p5)
344
		if ev == "key" and p1 == keys.enter then
345
			return true
346-
			local str = c:rep(math.floor(#text/#c)) .. c:sub(1,#text%#c)
346+
347
	end
348
	
349-
			class:write(text:sub(padding+1,padding+w+1),x,y,true)
349+
350
		-- fix cursor and padding
351
		if cursor > #text then cursor = #text end
352
		if cursor < 0 then cursor = 0 end
353
		if padding > #text-1 then padding = #text-1 end
354
		if padding < 0 then padding = 0 end
355
		
356
		-- drawing
357
		if trans ~= true then
358
			class:rect("fill",x,y,x+w,y,false)
359
		end
360
		local tbl = strtotbl(text)
361
		if type(c) == "string" then
362
			local str = c:rep(math.floor(#tbl/#c)) .. c:sub(1,#tbl%#c)
363
			class:write(str:sub(padding+1,padding+w+1),x,y,true)
364
		else
365
			local count = 0
366
			for index = padding+1,padding+w+1 do
367
				if text[index] then
368
					class:write(text[index],x+count,y,true)
369
				end
370
				count = count + 1
371
			end
372
		end
373
		
374
		class:update()
375
		class:draw()
376
		
377
		if cursor-padding <= w and cursor-padding >= 0 then
378
			class.obj.setCursorPos(x+cursor-padding,y)
379
			class.obj.setTextColor(class:getfgcolor())
380
			class.obj.setCursorBlink(true)
381
		end
382
		
383
		local ev,p1,p2,p3,p4,p5 = os.pullEvent()
384
		
385
		class.obj.setCursorBlink(false)
386
		
387
		if callback(ev,p1,p2,p3,p4,p5) == true then
388
			return text,ev,p1,p2,p3,p4,p5
389
		end
390
		if ev == "key" then
391
			if p1 == keys.left then
392
				-- move left
393
				cursor = cursor - 1
394
				if cursor<padding then padding = padding - 1 end
395
			elseif p1 == keys.right then
396
				-- move right
397
				cursor = cursor + 1
398
				if cursor-padding > w then padding = padding + 1 end
399
			elseif p1 == keys.backspace then
400
				-- remove a character
401
				local num = cursor-1
402
				if num < 0 then num = 0 end
403
				text = text:sub(1,num) .. text:sub(cursor+1)
404
				cursor = cursor - 1
405
				if cursor<padding then padding = padding - 1 end
406
			elseif p1 == keys.delete then
407
				-- remove a character
408
				text = text:sub(1,cursor) .. text:sub(cursor+2)
409
			elseif p1 == keys.home then
410
				cursor = 0
411
				padding = 0
412
			elseif p1 == keys["end"] then
413
				cursor = text:len()
414
				padding = text:len()-w
415
			end
416
		elseif ev == "char" then
417
			if #text < l or l <= 0 then -- check length limit
418
				-- add a character
419
				text = text:sub(1,cursor) .. p1 .. text:sub(cursor+1)
420
				cursor = cursor + 1
421
				if cursor-padding > w then padding = padding + 1 end
422
			end
423
		elseif (ev == "mouse_click" and class.type == "term")
424
		or (ev == "monitor_touch" and class.type == "monitor" and p1 == class.path) then
425
			-- move cursor
426
			-- x=p2, y=p3
427
			if p2<x then p2=x end
428
			if p2>x+w then p2=x+w end
429
			cursor = p2-x+padding
430
		elseif ev == "mouse_scroll" then
431
			-- scrolling left/right
432
			padding = padding + p1
433
		end
434
	end
435
end
436
437
function load(objpath)
438
	local startload = os.clock()
439
	
440
	tobj = {}
441
	
442
	-- object variables
443
	objpath = objpath or "N/A"
444
	if peripheral.isPresent(objpath)
445
	and peripheral.getType(objpath) == "monitor" then
446
		tobj.obj = peripheral.wrap(objpath or "N/A")
447
		tobj.type = "monitor"
448
		tobj.path = objpath
449
		tobj.eventname = "monitor_touch"
450
	else
451
		tobj.type = "term"
452
		tobj.obj = term
453
		tobj.path = "N/A"
454
		tobj.eventname = "mouse_click"
455
	end
456
	
457
	-- variables
458
	tobj.pixles = {}
459
	tobj.updaterate = 0.2
460
	tobj.looprunning = false
461
	tobj.looptime = 0
462
	tobj.stroke = 1
463
	tobj.bgcolor = colors.black
464
	tobj.fgcolor = colors.white
465
	
466
	-- misc functions
467
	tobj.setupdaterate = setupdaterate
468
	tobj.getupdaterate = getupdaterate
469
	tobj.removepixles = removepixles
470
	tobj.fixpixles = fixpixles
471
	tobj.update = update
472
	tobj.draw = draw
473
	tobj.loop = loop
474
	tobj.prepareloop = prepareloop
475
	tobj.stoploop = stoploop
476
	
477
	-- color functions
478
	tobj.setcolor = setcolor
479
	tobj.setfgcolor = setfgcolor
480
	tobj.setbgcolor = setbgcolor
481
	tobj.getcolor = getcolor
482
	tobj.getfgcolor = getfgcolor
483
	tobj.getbgcolor = getbgcolor
484
	tobj.setstroke = setstroke
485
	tobj.getstroke = getstroke
486
	-- british
487
	tobj.setcolour = setcolor
488
	tobj.setfgcolour = setfgcolor
489
	tobj.setbgcolour = setbgcolor
490
	tobj.getcolour = getcolor
491
	tobj.getfgcolour = getfgcolor
492
	tobj.getbgcolour = getbgcolor
493
	
494
	-- drawing functions
495
	tobj.clear = clear
496
	tobj.write = write
497
	tobj.line = line
498
	tobj.rect = rect
499
	tobj.circle = circle
500
	tobj.read = read
501
	
502
	tobj:removepixles()
503
	tobj:fixpixles()
504
	
505
	local endload = os.clock()
506
	return tobj,endload-startload
507
end