Advertisement
Tomlacko

ComputerCraft UI API

Apr 6th, 2019
448
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 12.85 KB | None | 0 0
  1. --------------------------------------------------
  2. --UTILS--
  3.  
  4. local function TableMerge(...)
  5.   local result = {}
  6.   for n,t in ipairs(arg) do
  7.     for obj,val in pairs(t) do
  8.       result[obj] = val
  9.     end
  10.   end
  11.   return result
  12. end
  13.  
  14.  
  15. --------------------------------------------------
  16. --ELEMENTS--
  17.  
  18. local Element = {}
  19. Element.__index = Element
  20. function NewElement(name, text, x1, y1, x2, y2, txtColor, bgrColor, hidden, enabled, align)
  21.   local elem = {
  22.     name=name,
  23.     x1=x1, y1=y1,
  24.     x2=x2, y2=y2,
  25.     enabled=enabled,
  26.     _enabled=true,
  27.     pressed=false,
  28.     hidden=hidden,
  29.     txtColor=txtColor,
  30.     txtColorPressed=txtColor,
  31.     txtColorDisabled=txtColor,
  32.     bgrColor=bgrColor,
  33.     bgrColorPressed=bgrColor,
  34.     bgrColorDisabled=bgrColor,
  35.     text=text,
  36.     align=align,
  37.     parent=nil,
  38.     disableDefaultDraw=false,
  39.     --onClick=nil,
  40.     --onBeforeDraw=nil,
  41.     --onAfterDraw=nil,
  42.   }
  43.   setmetatable(elem, Element)
  44.   return elem
  45. end
  46.  
  47.  
  48. function Element:Disable()
  49.   self.enabled = false
  50. end
  51.  
  52.  
  53. function Element:Enable()
  54.   self.enabled = self._enabled
  55. end
  56.  
  57.  
  58. function Element:Hide()
  59.   self.hidden = true
  60.  
  61.   if self.parent and self.parent.parent and self.parent.parent.scrollable then
  62.     self.parent.parent:UpdateScrolling()
  63.   end
  64. end
  65.  
  66.  
  67. function Element:Show()
  68.   self.hidden = false
  69.  
  70.   if self.parent and self.parent.parent and self.parent.parent.scrollable then
  71.     self.parent.parent:UpdateScrolling()
  72.   end
  73. end
  74.  
  75.  
  76. function Element:Move(dx, dy)
  77.   self.x1 = self.x1 + dx
  78.   self.x2 = self.x2 + dx
  79.   self.y1 = self.y1 + dy
  80.   self.y2 = self.y2 + dy
  81. end
  82.  
  83.  
  84. function Element:IsValidPoint(x, y, shallow)
  85.   if x<self.x1 or x>self.x2 or y<self.y1 or y>self.y2 then
  86.     return false
  87.   end
  88.   if not shallow and self.parent then
  89.     return self.parent:IsValidPoint(x, y, false)
  90.   end
  91.   return true
  92. end
  93.  
  94.  
  95. function Element:Draw(m)
  96.   if self.hidden then
  97.     return
  98.   end
  99.  
  100.   if self.onBeforeDraw then
  101.     self.onBeforeDraw(m)
  102.   end
  103.  
  104.   if not self.enabled then
  105.     if self.bgrColorDisabled then
  106.       m.setBackgroundColor(colors[self.bgrColorDisabled])
  107.     end
  108.     if self.txtColorDisabled then
  109.       m.setTextColor(colors[self.txtColorDisabled])
  110.     end
  111.   elseif self.pressed then
  112.     if self.bgrColorPressed then
  113.       m.setBackgroundColor(colors[self.bgrColorPressed])
  114.     end
  115.     if self.txtColorPressed then
  116.       m.setTextColor(colors[self.txtColorPressed])
  117.     end
  118.   else
  119.     if self.bgrColor then
  120.       m.setBackgroundColor(colors[self.bgrColor])
  121.     end
  122.     if self.txtColor then
  123.       m.setTextColor(colors[self.txtColor])
  124.     end
  125.   end
  126.  
  127.   local text = tostring(self.text)
  128.  
  129.   if not self.disableDefaultDraw then
  130.     local i = 1
  131.     if self.align=="middle" or self.align=="center" then
  132.       i = math.ceil(#text/2 - ((self.x2-self.x1+1)*(self.y2-self.y1+1))/2 + 1)
  133.     elseif self.align=="right" then
  134.       i = 1 + #text - (self.x2-self.x1+1)*(self.y2-self.y1+1)
  135.     end
  136.    
  137.     for y=self.y1, self.y2 do
  138.       for x=self.x1, self.x2 do
  139.        
  140.         if self:IsValidPoint(x, y, false) then
  141.           m.setCursorPos(x,y)
  142.           local ch=" "
  143.           if i>=1 and i<=#text then
  144.             ch = text:sub(i, i)
  145.           end
  146.           m.write(ch)
  147.         end
  148.         i=i+1
  149.        
  150.       end
  151.     end
  152.   end
  153.  
  154.   if self.onAfterDraw then
  155.     self.onAfterDraw(m)
  156.   end
  157. end
  158.  
  159.  
  160. function Element:Click(m, x, y, event, shallow)
  161.   if self.enabled and not self.hidden and self:IsValidPoint(x, y, shallow) then
  162.     if self.onClick then
  163.       local result = self.onClick(m, x, y, event)
  164.       if result == nil then
  165.         result = true
  166.       end
  167.       return true, {[self] = result}
  168.     else
  169.       return true, {[self] = true}
  170.     end
  171.   else
  172.     return false, {}
  173.   end
  174. end
  175.  
  176.  
  177.  
  178.  
  179. --------------------------------------------------
  180. --GROUPS--
  181.  
  182. local Group = {}
  183. Group.__index = Group
  184. function NewGroup(name, hidden, x1, y1, x2, y2)
  185.   local group = {
  186.     name=name,
  187.     hidden=hidden,
  188.     scrollable=false,
  189.     x1=x1, y1=y1,
  190.     x2=x2, y2=y2,
  191.     groups={},
  192.     elements={},
  193.     parent=nil,
  194.     --onBeforeDraw=nil,
  195.     --onAfterDraw=nil,
  196.   }
  197.   setmetatable(group, Group)
  198.   return group
  199. end
  200.  
  201.  
  202. function Group:AddElement(elem)
  203.   if self.elements[elem.name] then
  204.     error("Element '"..elem.name.."' already exists in this group!")
  205.   end
  206.   elem.parent = self
  207.   self.elements[elem.name] = elem
  208.  
  209.   if self.parent and self.parent.scrollable then
  210.     self.parent:UpdateScrolling()
  211.   end
  212. end
  213.  
  214.  
  215. function Group:AddGroup(group)
  216.   if self.groups[group.name] then
  217.     error("Group '"..group.name.."' already exists in this group!")
  218.   end
  219.   group.parent = self
  220.   self.groups[group.name] = group
  221.  
  222.   if self.parent and self.parent.scrollable then
  223.     self.parent:UpdateScrolling()
  224.   end
  225. end
  226.  
  227.  
  228. function Group:Disable()
  229.   for name,elem in pairs(self.elements) do
  230.     elem:Disable()
  231.   end
  232.   for name,group in pairs(self.groups) do
  233.     group:Disable()
  234.   end
  235. end
  236.  
  237.  
  238. function Group:Enable()
  239.   for name,elem in pairs(self.elements) do
  240.     elem:Enable()
  241.   end
  242.   for name,group in pairs(self.groups) do
  243.     group:Enable()
  244.   end
  245. end
  246.  
  247.  
  248. function Group:Hide()
  249.   self.hidden = true
  250.  
  251.   for name,elem in pairs(self.elements) do
  252.     elem:Hide()
  253.   end
  254.   for name,group in pairs(self.groups) do
  255.     group:Hide()
  256.   end
  257.  
  258.   if self.parent and self.parent.parent and self.parent.parent.scrollable then
  259.     self.parent.parent:UpdateScrolling()
  260.   end
  261. end
  262.  
  263.  
  264. function Group:Show()
  265.   self.hidden = false
  266.  
  267.   for name,elem in pairs(self.elements) do
  268.     elem:Show()
  269.   end
  270.   for name,group in pairs(self.groups) do
  271.     group:Show()
  272.   end
  273.  
  274.   if self.parent and self.parent.parent and self.parent.parent.scrollable then
  275.     self.parent.parent:UpdateScrolling()
  276.   end
  277. end
  278.  
  279.  
  280. function Group:UpdateScrolling(m)
  281.   if not self.scrollable then
  282.     error("Group is not scrollable!")
  283.   end
  284.  
  285.   local content = self.groups[self.name.."_content"]
  286.   local minX = math.huge
  287.   local minY = math.huge
  288.   local maxX = -math.huge
  289.   local maxY = -math.huge
  290.  
  291.   for name,elem in pairs(content.elements) do
  292.     if not elem.hidden then
  293.       minX = math.min(minX, elem.x1)
  294.       minY = math.min(minY, elem.y1)
  295.       maxX = math.max(maxX, elem.x2)
  296.       maxY = math.max(maxY, elem.y2)
  297.     end
  298.   end
  299.   for name,group in pairs(content.groups) do
  300.     if not group.hidden then
  301.       minX = math.min(minX, elem.x1)
  302.       minY = math.min(minY, elem.y1)
  303.       maxX = math.max(maxX, elem.x2)
  304.       maxY = math.max(maxY, elem.y2)
  305.     end
  306.   end
  307.  
  308.   if self.scrollable == "horizontal" or self.scrollable == "both" then
  309.     if minX < content.x1 then
  310.       self.elements.scrollLeft.enabled = true
  311.       self.elements.scrollLeft._enabled = true
  312.     else
  313.       self.elements.scrollLeft.enabled = false
  314.       self.elements.scrollLeft._enabled = false
  315.     end
  316.    
  317.     if maxX > content.x2 then
  318.       self.elements.scrollRight.enabled = true
  319.       self.elements.scrollRight._enabled = true
  320.     else
  321.       self.elements.scrollRight.enabled = false
  322.       self.elements.scrollRight._enabled = false
  323.     end
  324.   end
  325.  
  326.   if self.scrollable == "vertical" or self.scrollable == "both" then
  327.     if minY < content.y1 then
  328.       self.elements.scrollUp.enabled = true
  329.       self.elements.scrollUp._enabled = true
  330.     else
  331.       self.elements.scrollUp.enabled = false
  332.       self.elements.scrollUp._enabled = false
  333.     end
  334.    
  335.     if maxY > content.y2 then
  336.       self.elements.scrollDown.enabled = true
  337.       self.elements.scrollDown._enabled = true
  338.     else
  339.       self.elements.scrollDown.enabled = false
  340.       self.elements.scrollDown._enabled = false
  341.     end
  342.   end
  343.  
  344.   if m then
  345.     self:Draw(m)
  346.   end
  347. end
  348.  
  349.  
  350. function Group:MakeScrollable(H, V, txtColor, bgrColor, txtColorDisabled, bgrColorDisabled)
  351.   if self.scrollable then
  352.     error("Group already has scrolling!")
  353.   end
  354.  
  355.   if not H and not V then
  356.     error("No scrolling was specified")
  357.   end
  358.  
  359.   if H and V then
  360.     self.scrollable = "both"
  361.   elseif H then
  362.     self.scrollable = "horizontal"
  363.   else
  364.     self.scrollable = "vertical"
  365.   end
  366.  
  367.   if not H then
  368.     H = {size=0, step=0, iconLeft="", iconRight="", fake=true}
  369.   end
  370.   if not V then
  371.     V = {size=0, step=0, iconUp="", iconDown="", fake=true}
  372.   end
  373.  
  374.   local content = NewGroup(self.name.."_content", self.hidden, self.x1+H.size, self.y1+V.size, self.x2-H.size, self.y2-V.size)
  375.  
  376.   for name,elem in pairs(self.elements) do
  377.     content:AddElement(elem)
  378.   end
  379.   for name,group in pairs(self.groups) do
  380.     content:AddGroup(group)
  381.   end
  382.  
  383.   self.elements = {}
  384.   self.groups = {}
  385.   self:AddGroup(content)
  386.  
  387.   content:MoveContent(H.size, V.size)
  388.  
  389.   if not H.fake then
  390.     local scrollLeft = NewElement("scrollLeft", H.iconLeft, self.x1, self.y1, self.x1+H.size-1, self.y2, txtColor, bgrColor, self.hidden, false, "center")
  391.     local scrollRight = NewElement("scrollRight", H.iconRight, self.x2-H.size+1, self.y1, self.x2, self.y2, txtColor, bgrColor, self.hidden, false, "center")
  392.    
  393.     if txtColorDisabled then
  394.       scrollLeft.txtColorDisabled = txtColorDisabled
  395.       scrollRight.txtColorDisabled = txtColorDisabled
  396.     end
  397.     if bgrColorDisabled then
  398.       scrollLeft.bgrColorDisabled = bgrColorDisabled
  399.       scrollRight.bgrColorDisabled = bgrColorDisabled
  400.     end
  401.    
  402.     scrollLeft._enabled = false
  403.     scrollRight._enabled = false
  404.     scrollLeft.scrollStep = H.step
  405.     scrollRight.scrollStep = -H.step
  406.    
  407.     scrollLeft.onClick = function(m, x, y, event)
  408.       content:MoveContent(scrollLeft.scrollStep, 0)
  409.       self:UpdateScrolling(m)
  410.     end
  411.     scrollRight.onClick = function(m, x, y, event)
  412.       content:MoveContent(scrollRight.scrollStep, 0)
  413.       self:UpdateScrolling(m)
  414.     end
  415.    
  416.     self:AddElement(scrollLeft)
  417.     self:AddElement(scrollRight)
  418.   end
  419.  
  420.   if not V.fake then
  421.     local scrollUp = NewElement("scrollUp", V.iconUp, self.x1, self.y1, self.x2, self.y1+V.size-1, txtColor, bgrColor, self.hidden, false, "center")
  422.     local scrollDown = NewElement("scrollDown", V.iconDown, self.x1, self.y2, self.x2, self.y2-V.size+1, txtColor, bgrColor, self.hidden, false, "center")
  423.    
  424.     if txtColorDisabled then
  425.       scrollUp.txtColorDisabled = txtColorDisabled
  426.       scrollDown.txtColorDisabled = txtColorDisabled
  427.     end
  428.     if bgrColorDisabled then
  429.       scrollUp.bgrColorDisabled = bgrColorDisabled
  430.       scrollDown.bgrColorDisabled = bgrColorDisabled
  431.     end
  432.    
  433.     scrollUp._enabled = false
  434.     scrollDown._enabled = false
  435.     scrollUp.scrollStep = V.step
  436.     scrollDown.scrollStep = -V.step
  437.    
  438.     scrollUp.onClick = function(m, x, y, event)
  439.       content:MoveContent(0, scrollUp.scrollStep)
  440.       self:UpdateScrolling(m)
  441.     end
  442.     scrollDown.onClick = function(m, x, y, event)
  443.       content:MoveContent(0, scrollDown.scrollStep)
  444.       self:UpdateScrolling(m)
  445.     end
  446.    
  447.     self:AddElement(scrollUp)
  448.     self:AddElement(scrollDown)
  449.   end
  450.  
  451.   self:UpdateScrolling()
  452. end
  453.  
  454.  
  455. function Group:ApplyElemProperty(prop, val, recursive)
  456.   for name,elem in pairs(self.elements) do
  457.     elem[prop] = val
  458.   end
  459.  
  460.   if recursive then
  461.     for name,group in pairs(self.groups) do
  462.       group:ApplyElemProperty(prop, val, true)
  463.     end
  464.   end
  465. end
  466.  
  467.  
  468. function Group:Move(dx, dy)
  469.   self.x1 = self.x1 + dx
  470.   self.x2 = self.x2 + dx
  471.   self.y1 = self.y1 + dy
  472.   self.y2 = self.y2 + dy
  473.   self:MoveContent(dx, dy)
  474. end
  475.  
  476.  
  477. function Group:MoveContent(dx, dy)
  478.   for name,elem in pairs(self.elements) do
  479.     elem:Move(dx, dy)
  480.   end
  481.   for name,group in pairs(self.groups) do
  482.     group:Move(dx, dy)
  483.   end
  484. end
  485.  
  486.  
  487. function Group:Click(m, x, y, event, shallow)
  488.   if not self.hidden and self:IsValidPoint(x, y, shallow) then
  489.     local result = {}
  490.     local success = false
  491.    
  492.     for name,elem in pairs(self.elements) do
  493.       local s, r = elem:Click(m, x, y, event, true)
  494.       result = TableMerge(result, r)
  495.       success = s or success
  496.     end
  497.     for name,group in pairs(self.groups) do
  498.       local s, r = group:Click(m, x, y, event, true)
  499.       result = TableMerge(result, r)
  500.       success = s or success
  501.     end
  502.    
  503.     return success, result
  504.   else
  505.     return false, {}
  506.   end
  507. end
  508.  
  509.  
  510. function Group:IsValidPoint(x, y, shallow)
  511.   if x<self.x1 or x>self.x2 or y<self.y1 or y>self.y2 then
  512.     return false
  513.   end
  514.   if not shallow and self.parent then
  515.     return self.parent:IsValidPoint(x, y, false)
  516.   end
  517.   return true
  518. end
  519.  
  520.  
  521. function Group:Draw(m)
  522.   if self.hidden then
  523.     return
  524.   end
  525.  
  526.   if self.onBeforeDraw then
  527.     self.onBeforeDraw(m)
  528.   end
  529.  
  530.   for name,group in pairs(self.groups) do
  531.     group:Draw(m)
  532.   end
  533.   for name,elem in pairs(self.elements) do
  534.     elem:Draw(m)
  535.   end
  536.  
  537.   if self.onAfterDraw then
  538.     self.onAfterDraw(m)
  539.   end
  540. end
  541.  
  542.  
  543. function Group:GetMidX()
  544.   return (self.x1+self.x2)/2
  545. end
  546.  
  547.  
  548. function Group:GetMidY()
  549.   return (self.y1+self.y2)/2
  550. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement