Advertisement
Alakazard12

aGUI

Apr 19th, 2013
333
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 25.36 KB | None | 0 0
  1. --[[
  2. CREATED BY ALAKAZARD12 (Azelk)
  3.  
  4. This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License.
  5.  
  6. ]]
  7.  
  8. local cBack = nil
  9. local cText = nil
  10. local W, H = term.getSize()
  11. local touched
  12. local tTouched
  13.  
  14. local function round(n)
  15.     local raw = n - math.floor(n)
  16.     if raw > 0.5 then
  17.         return math.ceil(n)
  18.     else
  19.         return math.floor(n)
  20.     end
  21. end
  22.  
  23. local function listen(UI)
  24.     local output
  25.     if UI.output then
  26.         output = UI.output
  27.     end
  28.     local activeT
  29.     local lastClick
  30.     local tabOn = 0
  31.     local lastTabbed
  32.     local function clearTab()
  33.         if lastTabbed then
  34.             lastTabbed.Tabbed = false
  35.             UI:draw()
  36.             tabOn = 0
  37.             lastTabbed = nil
  38.         end
  39.     end
  40.     while true do
  41.         if UI.stopList == true then break end
  42.         local event, p1, p2, p3, p4, p5 = os.pullEventRaw()
  43.         if UI.output then
  44.             output = UI.output
  45.         end
  46.         if output then
  47.             output(event, p1, p2, p3, p4, p5)
  48.         end
  49.         if event == "mouse_drag" then
  50.             clearTab()
  51.             local check
  52.             function check(par, bg, fx, fy)
  53.                 table.sort(par, function(x, y)
  54.                     return x.zIndex > y.zIndex
  55.                 end)
  56.                 for i,v in ipairs(par) do
  57.                     if (v.visible == true and v.active == true) and (v.type == "button") then
  58.                         -- if p2 >= v.position[1] and p2 <= v.position[1] + v.size[1] - 1 and p3 >= v.position[2] and p3 <= v.position[2] + v.size[2] - 1 then
  59.                         if lastClick == v then
  60.                             if p1 == 1 then
  61.                                 if v.drag1Func then
  62.                                     v.drag1Func(p2, p3)
  63.                                 end
  64.                             elseif p1 == 2 then
  65.                                 if v.drag2Func then
  66.                                     v.drag2Func(p2, p3)
  67.                                 end
  68.                             elseif p1 == 3 then
  69.                                 if v.drag3Func then
  70.                                     v.drag3Func(p2, p3)
  71.                                 end
  72.                             end
  73.                         end
  74.                         if p2 >= v.position[1] and p2 <= v.position[1] + v.size[1] - 1 and p3 >= v.position[2] and p3 <= v.position[2] + v.size[2] - 1 then
  75.                             if p1 == 1 then
  76.                                 if v.drag1FuncO then
  77.                                     v.drag1FuncO(x, y)
  78.                                 end
  79.                             elseif p1 == 2 then
  80.                                 if v.drag2FuncO then
  81.                                     v.drag2FuncO(x, y)
  82.                                 end
  83.                             elseif p1 == 3 then
  84.                                 if v.drag3FuncO then
  85.                                     v.drag3FuncO(x, y)
  86.                                 end
  87.                             end
  88.                         end
  89.                     end
  90.                     if v.type == "frame" and v.active == true then
  91.                         if v.showBackground then
  92.                             check(v.children, v.backgroundColor, fx + v.position[1] - 1, fy + v.position[2] - 1)
  93.                         else
  94.                             check(v.children, bg, fx + v.position[1] - 1, fy + v.position[2] - 1)
  95.                         end
  96.                     end
  97.                 end
  98.             end
  99.             check(UI.Children, UI.backgroundColor, 0, 0)
  100.         elseif event == "key" then
  101.             if p1 == 15 then
  102.                 if tabOn == UI.maxTab then
  103.                     tabOn = 0
  104.                 else
  105.                     local nKey = 0
  106.                     local cKey
  107.                     local check
  108.                     function check(par, bg, fx, fy)
  109.                         table.sort(par, function(x, y)
  110.                             return x.zIndex > y.zIndex
  111.                         end)
  112.                         for i,v in ipairs(par) do
  113.                             if (v.canTab == true and v.active == true) and (v.type == "button" or v.type == "textbox") then
  114.                                 if v.tabIndex > tabOn then
  115.                                     if nKey == 0 then
  116.                                         nKey = v.tabIndex
  117.                                         cKey = v
  118.                                     end
  119.                                     if nKey - tabOn > v.tabIndex - tabOn then
  120.                                         nKey = v.tabIndex
  121.                                         cKey = v
  122.                                     end
  123.                                 end
  124.                             end
  125.                             if v.type == "frame" and v.active == true then
  126.                                 if v.showBackground then
  127.                                     check(v.children, v.backgroundColor, fx + v.position[1] - 1, fy + v.position[2] - 1)
  128.                                 else
  129.                                     check(v.children, bg, fx + v.position[1] - 1, fy + v.position[2] - 1)
  130.                                 end
  131.                             end
  132.                         end
  133.                     end
  134.                     check(UI.Children, UI.backgroundColor, 0, 0)
  135.                     clearTab()
  136.                     if cKey then
  137.                         cKey.Tabbed = true
  138.                         tabOn = nKey
  139.                         lastTabbed = cKey
  140.                         UI:draw()
  141.                     end
  142.                 end
  143.             end
  144.             if activeT then
  145.                 if p1 == 14 then
  146.                     activeT.text = string.sub(activeT.text, 1, #activeT.text - 1)
  147.                     activeT.rText = string.sub(activeT.rText, 1, #activeT.rText - 1)
  148.                     UI:draw()
  149.                 elseif p1 == 28 then
  150.                     activeT.isActive = false
  151.                     UI:draw()
  152.                     if activeT.textChangeFunc then
  153.                         activeT.textChangeFunc(activeT.rText)
  154.                     end
  155.                     activeT = nil
  156.                 end
  157.             else
  158.                 if p1 == 28 and lastTabbed then
  159.                     if lastTabbed.type == "textbox" then
  160.                         activeT = lastTabbed
  161.                         lastTabbed.isActive = true
  162.                         UI:draw()
  163.                     else
  164.                         if lastTabbed.enterPressFunc then
  165.                             lastTabbed.enterPressFunc()
  166.                         end
  167.                     end
  168.                     clearTab()
  169.                 end
  170.             end
  171.         elseif event == "char" then
  172.             if activeT then
  173.                 activeT.text = activeT.text .. (activeT.textChar or p1)
  174.                 activeT.rText = (activeT.rText or "") .. p1
  175.                 term.setTextColor(activeT.textColor)
  176.                 UI:draw()
  177.             end
  178.         elseif event == "mouse_click" then
  179.             local didPress = false
  180.             clearTab()
  181.             lastClick = nil
  182.             local check
  183.             function check(par, bg, fx, fy)
  184.                 if didPress == true then return end
  185.                 table.sort(par, function(x, y)
  186.                     return x.zIndex > y.zIndex
  187.                 end)
  188.                 for i,v in ipairs(par) do
  189.                     if v.visible == true and v.active == true and (v.type == "button" or v.type == "textbox") then
  190.                         if p2 >= v.position[1] + fx and p2 <= v.position[1] + v.size[1] + fx - 1 and p3 >= v.position[2] + fy and p3 <= v.position[2] + fy + v.size[2] - 1 then
  191.                             didPress = true
  192.                             lastClick = v
  193.                             if activeT then
  194.                                 activeT.isActive = false
  195.                                 if activeT.textChangeFunc then
  196.                                     activeT.textChangeFunc(activeT.rText)
  197.                                 end
  198.                                 activeT = nil
  199.                                 UI:draw()
  200.                             end
  201.                             if v.type == "button" then
  202.                                 if p1 == 1 and v.button1Func then
  203.                                     v.button1Func(p2, p3)
  204.                                 elseif p1 == 2 and v.button2Func then
  205.                                     v.button2Func(p2, p3)
  206.                                 elseif p1 == 3 and v.button3Func then
  207.                                     v.button3Func(p2, p3)
  208.                                 end
  209.                                 break
  210.                             elseif v.type == "textbox" then
  211.                                 activeT = v
  212.                                 if v.showText == true then
  213.                                     v.isActive = true
  214.                                     UI:draw()
  215.                                 end
  216.                                 break
  217.                             end
  218.                         end
  219.                     end
  220.                     if v.type == "frame" and v.active == true then
  221.                         if v.showBackground then
  222.                             check(v.children, v.backgroundColor, fx + v.position[1] - 1, fy + v.position[2] - 1)
  223.                         else
  224.                             check(v.children, bg, fx + v.position[1] - 1, fy + v.position[2] - 1)
  225.                         end
  226.                     end
  227.                 end
  228.             end
  229.             check(UI.Children, UI.backgroundColor, 0, 0)
  230.         end
  231.     end
  232. end
  233.  
  234. local function draw(UI)
  235.     if cBack == nil then
  236.         cBack = {}
  237.         term.setBackgroundColor(UI.backgroundColor)
  238.         term.clear()
  239.         for i = 1, W do
  240.             local pOn = {}
  241.             for y = 1, H do
  242.                 table.insert(pOn, UI.backgroundColor)
  243.             end
  244.             table.insert(cBack, pOn)
  245.         end
  246.     end
  247.     if cText == nil then
  248.         cText = {}
  249.         for i = 1, W do
  250.             local pOn = {}
  251.             for y = 1, H do
  252.                 table.insert(pOn, {" ", colors.white})
  253.             end
  254.             table.insert(cText, pOn)
  255.         end
  256.     end
  257.     tTouched = {}
  258.     touched = {}
  259.     for i = 1, W do
  260.         local pOn = {}
  261.         for y = 1, H do
  262.             table.insert(pOn, 0)
  263.         end
  264.         table.insert(touched, pOn)
  265.     end
  266.     for i = 1, W do
  267.         local pOn = {}
  268.         for y = 1, H do
  269.             table.insert(pOn, 0)
  270.         end
  271.         table.insert(tTouched, pOn)
  272.     end
  273.     local cusPos
  274.     local check
  275.     function check(par, bg, fx, fy)
  276.         table.sort(par, function(x, y)
  277.             return x.zIndex < y.zIndex
  278.         end)
  279.         for i,v in pairs(par) do
  280.             if v.visible == true and (v.type == "label" or v.type == "button" or v.type == "textbox" or v.type == "frame" or v.type == "image") then
  281.                 local Back = v.backgroundColor
  282.                 if v.Tabbed == true then
  283.                     Back = v.tabColor
  284.                 end
  285.                 if v.showBackground == false then
  286.                     Back = bg
  287.                 end
  288.                 term.setBackgroundColor(Back)
  289.                 if v.showBackground == true then
  290.                     for xs = 1, v.size[1] do
  291.                         for ys = 1, v.size[2] do
  292.                             local x = v.position[1] + xs - 1 + fx
  293.                             local y = v.position[2] + ys - 1 + fy
  294.                             if cBack[x] then
  295.                                 if cBack[x][y] ~= Back then
  296.                                     term.setBackgroundColor(Back)
  297.                                     term.setCursorPos(x, y)
  298.                                     term.write(" ")
  299.                                     cBack[x][y] = Back
  300.                                 end
  301.                                 touched[x][y] = 1
  302.                             end
  303.                         end
  304.                     end
  305.                 end
  306.                 if v.type == "image" then
  307.                     if v.image then
  308.                         paintutils.drawImage(v.image, v.position[1] + fx, v.position[2] + fy)
  309.                     end
  310.                 end
  311.                 if v.type == "label" or v.type == "button" or v.type == "textbox" then
  312.                     if v.showText == true then
  313.                         term.setTextColor(v.textColor)
  314.                         local text = v.text
  315.                         if v.isActive == true then
  316.                             text = text .. " "
  317.                         end
  318.                         if #text > v.size[1] then
  319.                             text = string.sub(text, #text - v.size[1] + 1, #text)
  320.                         end
  321.                         local x = v.position[1]
  322.                         local y = v.position[2]
  323.                         if v.xAlign == "center" then
  324.                             x = round((v.size[1] - #text) / 2 + v.position[1])
  325.                         elseif v.xAlign == "right" then
  326.                             x = round(v.size[1] - #text + v.position[1])
  327.                         end
  328.                         term.setCursorPos(x + fx, y + fy)
  329.                         term.write(text)
  330.  
  331.                         for i = 1, #text do
  332.                             local on = string.sub(text, i, i)
  333.                             if cBack[x + fx + i - 1][y + fy] then
  334.                                 if cText[x + fx + i - 1][y + fy] ~= on or cBack[x + fx + i - 1][y + fy] ~= Back then
  335.                                     term.setCursorPos(x + fx + i - 1, y + fy)
  336.                                     term.write(on)
  337.                                     cText[x + fx + i - 1][y + fy] = on
  338.                                     cBack[x + fx + i - 1][y + fy] = Back
  339.                                 end
  340.                                 tTouched[x + fx + i - 1][y + fy] = 1
  341.                             end
  342.                         end
  343.                         if v.isActive == true then
  344.                             cusPos = {x + #text - 1 + fx, y + fy, v.textColor}
  345.                         end
  346.                     end
  347.                 end
  348.                 if v.type == "frame" then
  349.                     if v.showBackground then
  350.                         check(v.children, v.backgroundColor, fx + v.position[1] - 1, fy + v.position[2] - 1)
  351.                     else
  352.                         check(v.children, bg, fx + v.position[1] - 1, fy + v.position[2] - 1)
  353.                     end
  354.                 end
  355.             end
  356.         end
  357.     end
  358.     check(UI.Children, UI.backgroundColor, 0, 0)
  359.     for i,x in pairs(touched) do
  360.         for y,t in pairs(x) do
  361.             term.setCursorPos(1, 1)
  362.             if t == 0 then
  363.                 term.setCursorPos(i, y)
  364.                 term.setBackgroundColor(UI.backgroundColor)
  365.                 term.write(" ")
  366.                 cBack[i][y] = UI.backgroundColor
  367.             end
  368.         end
  369.     end
  370.  
  371.     for i,x in pairs(tTouched) do
  372.         for y,t in pairs(x) do
  373.             term.setCursorPos(1, 1)
  374.             if t == 0 then
  375.                 term.setCursorPos(i, y)
  376.                 term.setBackgroundColor(cBack[i][y])
  377.                 term.write(" ")
  378.                 -- cBack[i][y] = UI.backgroundColor
  379.             end
  380.         end
  381.     end
  382.  
  383.     if cusPos then
  384.         term.setCursorPos(cusPos[1], cusPos[2])
  385.         term.setTextColor(cusPos[3])
  386.         term.setCursorBlink(true)
  387.     else
  388.         term.setCursorBlink(false)
  389.     end
  390. end
  391.  
  392. local function newUI()
  393.     -- Start creating the GUI
  394.     local UI = {}
  395.     UI.maxTab = 1
  396.     UI.Children = {}
  397.     UI.backgroundColor = colors.cyan
  398.    
  399.     function UI:checkTabs()
  400.         local high = 0
  401.         local check
  402.         function check(par)
  403.             for i,v in pairs(par) do
  404.                 if v.tabIndex then
  405.                     if v.tabIndex > high then
  406.                         high = v.tabIndex
  407.                     end
  408.                 end
  409.                 if v.type == "frame" then
  410.                     check(v.children)
  411.                 end
  412.             end
  413.         end
  414.         check(UI.Children)
  415.         UI.maxTab = high
  416.     end
  417.  
  418.     function UI:setOutput(func)
  419.         UI.output = func
  420.     end
  421.    
  422.     function UI:stopListen()
  423.         UI.stopList = true
  424.     end
  425.  
  426.     function UI:setBackgroundColor(color)
  427.         UI.backgroundColor = color
  428.     end
  429.    
  430.     function UI:draw()
  431.         draw(UI)
  432.     end
  433.    
  434.     function UI:listen()
  435.         UI.stopList = false
  436.         listen(UI)
  437.     end
  438.    
  439.     function UI:create(iType, par)
  440.         iType = iType:lower()
  441.         local ins
  442.         if iType == "checkbox" then
  443.             ins = {}
  444.             ins.canTab = true
  445.             ins.visible = true
  446.             ins.showBackground = true
  447.             ins.active = true
  448.             ins.char = "X"
  449.             ins.value = false
  450.             ins.backgroundColor = colors.gray
  451.             ins.textColor = colors.white
  452.             ins.tabIndex = 1
  453.             ins.tabColor = colors.blue
  454.            
  455.             function ins:setChar(char)
  456.                 ins.char = char
  457.             end
  458.            
  459.             function ins:setValue(val)
  460.                 ins.value = val
  461.             end
  462.            
  463.             function ins:setBackgroundColor(color)
  464.                 ins.backgroundColor = color
  465.             end
  466.  
  467.            
  468.             function ins:setTextColor(color)
  469.                 ins.textColor = color
  470.             end
  471.            
  472.             function ins:setTabColor(color)
  473.                 ins.tabColor = color
  474.             end
  475.            
  476.             function ins:setTabIndex(i)
  477.                 ins.tabIndex = i
  478.                 UI:checkTabs()
  479.             end
  480.         elseif iType == "frame" then
  481.             ins = {}
  482.             ins.visible = true
  483.             ins.showBackground = true
  484.             ins.type = iType
  485.             ins.backgroundColor = colors.orange
  486.             ins.size = {10, 3}
  487.             ins.position = {1, 1}
  488.             ins.zIndex = 1
  489.             ins.children = {}
  490.             ins.active = true
  491.  
  492.             function ins:setZIndex(i)
  493.                 ins.zIndex = i
  494.             end
  495.  
  496.             function ins:setActive(b)
  497.                 ins.active = b
  498.             end
  499.  
  500.             function ins:setVisible(b)
  501.                 ins.visible = b
  502.             end
  503.  
  504.             function ins:setShowBackground(b)
  505.                 ins.showBackground = b
  506.             end
  507.  
  508.             function ins:setBackgroundColor(color)
  509.                 ins.backgroundColor = color
  510.             end
  511.  
  512.             function ins:setSize(x, y)
  513.                 ins.size = {x, y}
  514.             end
  515.  
  516.             function ins:getSize()
  517.                 return ins.size[1], ins.size[2]
  518.             end
  519.  
  520.             function ins:getPosition()
  521.                 return ins.position[1], ins.position[2]
  522.             end
  523.  
  524.             function ins:setPosition(x, y)
  525.                 ins.position = {x, y}
  526.             end
  527.  
  528.             function ins:getBackgroundColor()
  529.                 return ins.backgroundColor
  530.             end
  531.         elseif iType == "image" then
  532.             ins = {}
  533.             ins.visible = true
  534.             ins.type = iType
  535.             ins.image = nil
  536.             ins.zIndex = 1
  537.             ins.backgroundColor = colors.black
  538.             ins.size = {8, 8}
  539.             ins.position = {1, 1}
  540.             ins.showBackground = true
  541.  
  542.             function ins:setShowBackground(b)
  543.                 ins.showBackground = b
  544.             end
  545.  
  546.             function ins:setVisible(b)
  547.                 ins.visible = b
  548.             end
  549.  
  550.             function ins:setImage(i)
  551.                 ins.image = i
  552.             end
  553.  
  554.             function ins:setZIndex(i)
  555.                 ins.zIndex = i
  556.             end
  557.  
  558.             function ins:setBackgroundColor(col)
  559.                 ins.backgroundColor = col
  560.             end
  561.  
  562.             function ins:setSize(x, y)
  563.                 ins.size = {x, y}
  564.             end
  565.  
  566.             function ins:setPosition(x, y)
  567.                 ins.position = {x, y}
  568.             end
  569.  
  570.             function ins:getPosition()
  571.                 return unpack(ins.position)
  572.             end
  573.  
  574.             function ins:getSize()
  575.                 return unpack(ins.size)
  576.             end
  577.         elseif iType == "button" or iType == "label"  or iType == "textbox" then
  578.             ins = {}
  579.             ins.canTab = true
  580.             ins.tabIndex = 1
  581.             ins.tabColor = colors.blue
  582.             ins.xAlign = "left"
  583.             ins.visible = true
  584.             ins.active = true
  585.             ins.showBackground = true
  586.             ins.showText = true
  587.             ins.type = iType
  588.             ins.backgroundColor = colors.gray
  589.             ins.textColor = colors.white
  590.             ins.text = iType
  591.             ins.rText = iType
  592.             ins.size = {6, 1}
  593.             ins.position = {1, 1}
  594.             ins.zIndex = 1
  595.  
  596.             function ins:setActive(b)
  597.                 ins.active = b
  598.             end
  599.  
  600.             function ins:getBackgroundColor()
  601.                 return ins.backgroundColor
  602.             end
  603.  
  604.             function ins:getTextColor()
  605.                 return ins.textColor
  606.             end
  607.  
  608.             function ins:getXAlign()
  609.                 return ins.xAlign
  610.             end
  611.            
  612.             function ins:setZIndex(i)
  613.                 ins.zIndex = i
  614.             end
  615.            
  616.             function ins:setTabIndex(i)
  617.                 ins.tabIndex = i
  618.                 UI:checkTabs()
  619.             end
  620.            
  621.             function ins:setTabColor(color)
  622.                 ins.tabColor = color
  623.             end
  624.            
  625.             function ins:setTextColor(color)
  626.                 ins.textColor = color
  627.             end
  628.            
  629.             function ins:setShowBackground(bool)
  630.                 ins.showBackground = bool
  631.             end
  632.            
  633.             function ins:setShowText(bool)
  634.                 ins.showText = bool
  635.             end
  636.            
  637.             function ins:setXAlign(t)
  638.                 ins.xAlign = t
  639.             end
  640.            
  641.             function ins:setVisible(bool)
  642.                 ins.visible = bool
  643.             end
  644.            
  645.             function ins:setBackgroundColor(color)
  646.                 ins.backgroundColor = color
  647.             end
  648.            
  649.             function ins:setSize(x, y)
  650.                 ins.size = {round(x), round(y)}
  651.             end
  652.            
  653.             function ins:setPosition(x, y)
  654.                 ins.position = {round(x), round(y)}
  655.             end
  656.            
  657.             function ins:getPosition()
  658.                 return unpack(ins.position)
  659.             end
  660.            
  661.             function ins:getSize()
  662.                 return unpack(ins.size)
  663.             end
  664.            
  665.             function ins:setText(text)
  666.                 ins.text = text or "nil"
  667.                 ins.rText = text or "nil"
  668.             end
  669.            
  670.             function ins:getText()
  671.                 return ins.rText or "nil"
  672.             end
  673.            
  674.             if iType == "textbox" then
  675.                 function ins:setTextChar(char)
  676.                     ins.textChar = char
  677.                 end
  678.                
  679.                 function ins.textChange(func)
  680.                     ins.textChangeFunc = func
  681.                 end
  682.             end
  683.            
  684.             if iType == "button" then
  685.                 function ins.button1DragOver(func)
  686.                     ins.drag1FuncO = func
  687.                 end
  688.  
  689.                 function ins.button2DragOver(func)
  690.                     ins.drag2FuncO = func
  691.                 end
  692.  
  693.                 function ins.button3DragOver(func)
  694.                     ins.drag3FuncO = func
  695.                 end
  696.  
  697.                 function ins.button1Drag(func)
  698.                     ins.drag1Func = func
  699.                 end
  700.                
  701.                 function ins.button2Drag(func)
  702.                     ins.drag2Func = func
  703.                 end
  704.                
  705.                 function ins.button3Drag(func)
  706.                     ins.drag3Func = func
  707.                 end
  708.                
  709.                 function ins.button1Click(func)
  710.                     ins.button1Func = func
  711.                 end
  712.                
  713.                 function ins.enterPress(func)
  714.                     ins.enterPressFunc = func
  715.                 end
  716.                
  717.                 function ins.button2Click(func)
  718.                     ins.button2Func = func
  719.                 end
  720.                
  721.                 function ins.button3Click(func)
  722.                     ins.button3Func = func
  723.                 end
  724.             end
  725.         end
  726.  
  727.         function ins:destroy()
  728.             local li
  729.             if par then
  730.                 li = par.children
  731.             else
  732.                 li = UI.Children
  733.             end
  734.             for i,v in pairs(li) do
  735.                 if v == ins then
  736.                     table.remove(li, i)
  737.                     break
  738.                 end
  739.             end
  740.         end
  741.  
  742.         if par then
  743.             table.insert(par.children, ins)
  744.         else
  745.             table.insert(UI.Children, ins)
  746.         end
  747.         return ins
  748.     end
  749.     return UI
  750. end
  751.  
  752. function new()
  753.     local UI = newUI()
  754.     return UI
  755. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement