Advertisement
jille_Jr

CC: Display API w/ Unicode support

Nov 17th, 2013
139
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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.         str=str..tostring(value)
  325.     end
  326. end
  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.         end
  347.     end
  348.    
  349.     while running do
  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
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement