Advertisement
LazyShpee

flexibleAPI v2.1

Mar 28th, 2013
72
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 14.20 KB | None | 0 0
  1. -- ######################################## --
  2. --                                          --
  3. -- Better UI API for ComputerCraft v2 inDev --
  4. --                                          --
  5. -- ######################################## --
  6.  
  7. -- ################################################################################
  8. --
  9. -- Base functions being used for many things
  10. function cur(target, x, y) target.setCursorPos(x, y) end
  11. function color(target,fg,bg) if fg ~= 0 then target.setTextColor(fg) end if bg ~= 0 then target.setBackgroundColor(bg) end end
  12. function drawPixel(target, x, y, nColour) if nColour then term.setBackgroundColor( nColour ) end cur(target, x, y) v.write(' ') end
  13. function split(se,sep) local sep, fields = sep or ":", {} local pattern = string.format("([^%s]+)", sep) se:gsub(pattern, function(c) fields[#fields+1] = c end) return fields end
  14. function inTable(tbl, item)
  15.     if type(item) == 'table' then
  16.         for i, v in pairs(item) do for key,value in pairs(tbl) do if value == v then return i, key end end end
  17.     elseif type(item) == 'string' then
  18.         for key,value in pairs(tbl) do if value == item then return key end end
  19.     end
  20.     return 0
  21. end
  22. function unpackPat(tbl, pattern)
  23.     local a = {}
  24.     for i, v in ipairs(pattern) do
  25.         a[i] = tbl[v]
  26.     end
  27.     return unpack(a)
  28. end
  29. function contPos(self,x,y,cont)
  30.     local loop = true
  31.     newx, newy = 0, 0
  32.     while loop do
  33.         newx = newx + self.ui[cont].x
  34.         newy = newy + self.ui[cont].y
  35.         if self.ui[cont].cont then
  36.             cont = self.ui[cont].cont
  37.         else
  38.             loop = false
  39.         end
  40.         return newx, newy
  41.     end
  42. end
  43. function pairsByKey(t, f)
  44.     local a = {}
  45.     for n in pairs(t) do table.insert(a, n) end
  46.         table.sort(a, f)
  47.         local i = 0      -- iterator variable
  48.         local iter = function ()   -- iterator function
  49.         i = i + 1
  50.         if a[i] == nil then return nil
  51.             else return a[i], t[a[i]]
  52.         end
  53.     end
  54.     return iter
  55. end
  56. --
  57. -- ################################################################################
  58.  
  59. -- ################################################################################
  60. -- New UI list constructor
  61. --
  62. function new(defTag, defDis)
  63.     local uiList = {}
  64.             uiList.ui = {}
  65.             uiList.set = {}
  66.             uiList.get = {}
  67.             uiList.utils = {}
  68.             uiList.config = {}
  69.                 uiList.config.defDis = defDis or {term}
  70.                 uiList.config.defTag = defTag or {'all'}
  71.                 uiList.config.defFG = colors.white
  72.                 uiList.config.defBG = colors.black
  73.                 uiList.config.pattern = {} -- Defines the patterns the different element types use that can be edited (setCommonAttribute)
  74.                     uiList.config.pattern.button = {'x', 'y', 'colors', 'tag', 'display', 'text', 'enabled', 'exe', 'ret', 'visible', 'cont'}
  75.                     uiList.config.pattern.label = {'x', 'y', 'colors', 'tag', 'display', 'text', 'enabled', 'cont'}
  76.                     uiList.config.pattern.radio = {'x', 'y', 'colors', 'tag', 'display', 'text', 'enabled', 'exe', 'ret', 'visible', 'value', 'cont'}
  77.                     uiList.config.pattern.checkbox = {'x', 'y', 'colors', 'tag', 'display', 'text', 'enabled', 'exe', 'ret', 'visible', 'value', 'cont'}
  78.                     uiList.config.pattern.point = {'x', 'y', 'colors', 'text', 'enabled', 'cont'}
  79.                
  80.         function uiList:addPoint(key, x, y, enabled) -- Add a point used to mark position
  81.             if not(key) or not(x) or not(y) then return false end
  82.             self.ui[key] = {name = key, type = 'point', x = x, y = y, enabled = true}
  83.             local temp = self.ui[key]
  84.             function temp:setColors(fg,bg) self.colors = {fg, bg} end
  85.             return self.ui[key]
  86.         end
  87.        
  88.         function uiList:addLabel(key, x, y, text, tag, display)
  89.             if not(key) or not(x) or not(y) or not(text) or self.ui[key] then return false end
  90.             self.ui[key] = {name = key, type = 'label', x = x, y = y, text = text, tag = tag or self.config.defTag, display = display or self.config.defDis, visible = true, enabled = true}
  91.             local temp = self.ui[key]
  92.             function temp:setColors(fg,bg) self.colors = {fg, bg} end
  93.             return self.ui[key]
  94.         end
  95.        
  96.         function uiList:addButton(key, x, y, text, tag, display)
  97.             if not(key) or not(x) or not(y) or not(text) then return false end
  98.             self.ui[key] = {name = key, type = 'button', x = x, y = y, text = text, tag = tag or self.config.defTag, display = display or self.config.defDis, visible = true, enabled = true}
  99.             local temp = self.ui[key]
  100.             function temp:setColors(fg,bg) self.colors = {fg, bg} end
  101.             function temp:setAction(act) if type(act) == 'function' then self.exe = act else self.ret = act end end
  102.             return self.ui[key]
  103.         end
  104.        
  105.         function uiList:addRadio(key, x, y, text, tag, display)
  106.             if not(key) or not(x) or not(y) or not(text) then return false end
  107.             self.ui[key] = {name = key, type = 'radio', x = x, y = y, text = text, tag = tag or self.config.defTag, display = display or self.config.defDis, visible = true, enabled = true, value = 0}
  108.             local temp = self.ui[key]
  109.             function temp:setColors(fg,bg) self.colors = {fg, bg} end
  110.             function temp:setAction(act) if type(act) == 'function' then self.exe = act else self.ret = act end end
  111.             function temp:setChar(disabled, enabled) self.custChar = disabled..enabled end
  112.             return self.ui[key]
  113.         end
  114.        
  115.         function uiList:addCheckbox(key, x, y, text, tag, display)
  116.             if not(key) or not(x) or not(y) or not(text) then return false end
  117.             self.ui[key] = {name = key, type = 'checkbox', x = x, y = y, text = text, tag = tag or self.config.defTag, display = display or self.config.defDis, visible = true, enabled = true, value = 0}
  118.             local temp = self.ui[key]
  119.             function temp:setColors(fg,bg) self.colors = {fg, bg} end
  120.             function temp:setAction(act) if type(act) == 'function' then self.exe = act else self.ret = act end end
  121.             function temp:setChar(disabled, enabled) self.custChar = disabled..enabled end
  122.             return self.ui[key]
  123.         end
  124.  
  125.         function uiList:del(key) self.ui[key] = nil return true end -- Working
  126.        
  127.         function uiList:draw(tags)
  128.             local ut = self.utils
  129.             local tags = tags or self.config.tag or self.config.defTag
  130.             for key, value in ut.pairsByKey(self.ui) do
  131.                 local t, x, y, text, tag, display, enabled= ut.unpackPat(value,{'type', 'x', 'y', 'text', 'tag', 'display', 'enabled'})
  132.                 local visible = value.visible
  133.                 if visible == nil then
  134.                     local visible = true
  135.                 end
  136.                 local colors = value.colors
  137.                 local cont = value.cont
  138.                 local custChar = value.custChar
  139.                 local val = value.value
  140.                 f, b = nil, nil
  141.                 if colors then f, b = unpack(colors) end
  142.                 if cont and self.ui[cont] then
  143.                     x = self.ui[cont].x + x
  144.                     y = self.ui[cont].y + y
  145.                     if not(b) and self.ui[cont].colors then
  146.                         b = self.ui[cont].colors[2]
  147.                     end
  148.                     enabled = self.ui[cont].enabled
  149.                 end
  150.                 fg = f or self.config.defFG
  151.                 bg = b or self.config.defBG
  152.                 if enabled and visible and t ~= 'point' and ut.inTable(tags, tag) > 0 then
  153.                     if type(text) == 'table' then
  154.                         local textMax = 0
  155.                         for i, v in ipairs(text) do
  156.                             if type(v) ~= 'table' and v:len() > textMax then textMax = v:len() end
  157.                             if type(v) == 'table' and v[1]:len() > textMax then textMax = v[1]:len() end
  158.                         end
  159.                         for i, v in ipairs(text) do
  160.                             if type(v) ~= 'table' and v:len() < textMax then text[i] = text[i]..string.rep(' ', textMax - v:len()) end
  161.                             if type(v) == 'table' and v[1]:len() < textMax then text[i][1] = text[i][1]..string.rep(' ', textMax - v[1]:len()) end
  162.                         end
  163.                     end
  164.                     for _, dis in pairs(display) do
  165.                         ut.color(dis, fg, bg)
  166.                         if type(text) == 'table' then
  167.                             for i, v in ipairs(text) do
  168.                                 ut.color(dis, fg, bg)
  169.                                 ut.cur(dis, x, y + (i - 1))
  170.                                 if type(v) == 'table' then
  171.                                     subTxt, subFG, subBG = unpack(v)
  172.                                     ut.color(dis, subFG, subBG)
  173.                                     dis.write(subTxt)
  174.                                 else
  175.                                     dis.write(v)
  176.                                 end
  177.                             end
  178.                         else
  179.                             if t == 'radio' or t == 'checkbox' then
  180.                                 custChar = custChar or 'O0'
  181.                                 if #custChar > 1 then
  182.                                     text = custChar:sub(1+val,1+val)..text
  183.                                 end
  184.                             end
  185.                             ut.cur(dis, x, y)
  186.                             dis.write(text)
  187.                         end
  188.                     end
  189.                 end
  190.             end
  191.             return true
  192.         end
  193.        
  194.         function uiList:mouse(pos, tags, display)
  195.             local ut = self.utils
  196.             local mx, my = unpack(pos)
  197.             tags = tags or self.config.defTag
  198.             disp = display or self.config.defDis
  199.             clicked = {}
  200.             for key, value in ut.pairsByKey(self.ui) do
  201.                 t, x, y, text, tag, display, enabled = ut.unpackPat(value,{'type', 'x', 'y', 'text', 'tag', 'display', 'enabled'})
  202.                 if ut.inTable(tags, tag) > 0 and enabled and ut.inTable({'button','radio','checkbox'}, t) > 0 then             
  203.                     local cont = value.cont
  204.                     if cont and self.ui[cont] then
  205.                         x = self.ui[cont].x + x
  206.                         y = self.ui[cont].y + y
  207.                     end
  208.                     if type(text) == 'table' then
  209.                         local textMax = 0 for _, v in ipairs(text) do if type(v) == 'table' then v = v[1] end if v:len() > textMax then textMax = v:len() end end
  210.                         if my >= y and my <= y - 1 + #text and mx >= x and mx <= (x - 1 + textMax) then
  211.                             table.insert(clicked, {value.ret, key, {mx + 1 - x, my + 1 - y}})
  212.                         end
  213.                     else
  214.                         if t == 'radio' or t == 'checkbox' then text = text..' ' end
  215.                         if my == y and mx >= x and mx <= (x + text:len() - 1) then
  216.                             table.insert(clicked, {value.ret, key, {mx + 1 - x, my + 1 - y}})
  217.                         end
  218.                     end
  219.                 end
  220.             end
  221.             if #clicked == 0 then
  222.                 return nil
  223.             else
  224.                 for i, v in pairs(clicked) do
  225.                     local curList = self.ui[v[2]]
  226.                     if curList.type == 'radio' and curList.cont then
  227.                         if curList.value == 0 then
  228.                             grp = curList.cont
  229.                             for ind, val in pairs(self.ui) do
  230.                                 if val['type'] == 'radio' and val.cont and val.cont == curList.cont then
  231.                                     if val.value ~= 0 then val.value = 0 end
  232.                                 end
  233.                             end
  234.                             curList.value = 1
  235.                         end
  236.                         if curList.exe and type(curList.exe) == 'function' then
  237.                             curList:exe(self)
  238.                         end
  239.                     elseif curList.type == 'checkbox' then
  240.                         if curList.value == 0 then
  241.                             curList.value = 1
  242.                         else
  243.                             curList.value = 0
  244.                         end
  245.                     elseif curList.type == 'button' then
  246.                         if curList.exe and type(curList.exe) == 'function' then
  247.                             curList:exe(self)
  248.                         end
  249.                     end
  250.                 end
  251.                 return clicked
  252.             end
  253.         end
  254.        
  255.         -- ################################################################################
  256.         --
  257.         -- Utils functions, contains the draw shapes 'n' stuff with some string utils
  258.         function uiList:getRadio(cont) for i, v in pairs(self.ui) do if v.type == 'radio' and v.value == 1 and v.cont == cont then return v end end return nil end
  259.         function uiList:getCheckbox(cont) local res = {} for i, v in pairs(self.ui) do if v.type == 'checkbox' and v.value == 1 and v.cont == cont then table.insert(res, v) end end if #res > 0 then return res else return nil end end
  260.         function uiList:setCommonAttribute(regEx, attrib)
  261.             for key, val in pairs(self.ui) do
  262.                 local validate = true
  263.                 local ut = self.utils
  264.                 for i, v in pairs(regEx) do
  265.                     if not(val[i]) or not(val[i]:find(v)) then
  266.                         validate = false
  267.                         break
  268.                     end
  269.                 end
  270.                 if validate then
  271.                     t = val.type
  272.                     for i, v in pairs(attrib) do
  273.                         if ut.inTable(self.config.pattern[t], i) > 0 then
  274.                             val[i] = v
  275.                         end
  276.                     end
  277.                 end
  278.             end
  279.         end
  280.         uiList.utils.pairsByKey = pairsByKey
  281.         uiList.utils.draw = {}
  282.         uiList.utils.dbg = function(p) print( ' <> ',p,' <> ') sleep(2) end
  283.         uiList.utils.draw.line = line
  284.         uiList.utils.draw.box = box
  285.         uiList.utils.draw.outline = outline
  286.         uiList.utils.unpackPat = unpackPat
  287.         uiList.utils.cur = cur
  288.         uiList.utils.color = color
  289.         uiList.utils.split = split
  290.         uiList.utils.inTable = inTable
  291.         --
  292.         -- ################################################################################
  293.     return uiList
  294. end
  295. --
  296. -- End of new() constructor
  297. -- ################################################################################
  298.  
  299.  
  300.  
  301.  
  302.  
  303.  
  304. function drawOutline(x1,y1, x2, y2, target, c)
  305.     drawLine(x1,y1, x1, y2, target, c)
  306.     drawLine(x1,y2, x2, y2, target, c)
  307.     drawLine(x2,y1, x2, y2, target, c)
  308.     drawLine(x1,y1, x2, y1, target, c)
  309. end
  310. function outline(self, x1,y1, x2, y2, target, c)
  311.     self.line(x1,y1, x1, y2, target, c)
  312.     self.line(x1,y2, x2, y2, target, c)
  313.     self.line(x2,y1, x2, y2, target, c)
  314.     self.line(x1,y1, x2, y1, target, c)
  315. end
  316.  
  317. -- function from paintutils ported for using targets
  318. local function drawPixelInternal( xPos, yPos, target )
  319.     target.setCursorPos(xPos, yPos)
  320.     target.write(" ")
  321. end
  322.  
  323. -- function to draw a filled box on target
  324. function drawBox(startX, startY, endX, endY, target, nColour)
  325.     if startY <= endY then s = 1 else s= -1 end
  326.     for index=startY, endY, s do
  327.         drawLine( startX, index, endX, index, target, nColour )
  328.     end
  329. end
  330. function box(self, startX, startY, endX, endY, target, nColour)
  331.     if startY <= endY then s = 1 else s= -1 end
  332.     for index=startY, endY, s do
  333.         self.line( startX, index, endX, index, target, nColour )
  334.     end
  335. end
  336.  
  337. -- function to draw line using targets
  338. function drawLine(startX, startY, endX, endY, target, nColour)
  339.     for i, v in pairs(target) do
  340.         line( startX, startY, endX, endY, v, nColour )
  341.     end
  342. end
  343.  
  344. -- function from paintutils ported for using targets
  345. local function line(startX, startY, endX, endY, v, nColour )
  346.    
  347.     local function drawPixelInternal( xPos, yPos, target ) target.setCursorPos(xPos, yPos) target.write(" ") end
  348.    
  349.     if nColour then
  350.         v.setBackgroundColor( nColour )
  351.     end
  352.  
  353.     startX = math.floor(startX)
  354.     startY = math.floor(startY)
  355.     endX = math.floor(endX)
  356.     endY = math.floor(endY)
  357.    
  358.     if startX == endX and startY == endY then
  359.         drawPixelInternal( startX, startY, v )
  360.         return
  361.     end
  362.    
  363.     local minX = math.min( startX, endX )
  364.     if minX == startX then
  365.         minY = startY
  366.         maxX = endX
  367.         maxY = endY
  368.     else
  369.         minY = endY
  370.         maxX = startX
  371.         maxY = startY
  372.     end
  373.        
  374.     local xDiff = maxX - minX
  375.     local yDiff = maxY - minY
  376.            
  377.     if xDiff > math.abs(yDiff) then
  378.         local y = minY
  379.         local dy = yDiff / xDiff
  380.         for x=minX,maxX do
  381.             drawPixelInternal( x, math.floor( y + 0.5 ), v )
  382.             y = y + dy
  383.         end
  384.     else
  385.         local x = minX
  386.         local dx = xDiff / yDiff
  387.         if maxY >= minY then
  388.             for y=minY,maxY do
  389.                 drawPixelInternal( math.floor( x + 0.5 ), y, v )
  390.                 x = x + dx
  391.             end
  392.         else
  393.             for y=minY,maxY,-1 do
  394.                 drawPixelInternal( math.floor( x + 0.5 ), y, v )
  395.                 x = x - dx
  396.             end
  397.         end
  398.     end
  399. end
  400. --
  401. -- ################################################################################
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement