DennouNeko

gui.lua

Mar 1st, 2025 (edited)
464
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 8.67 KB | Gaming | 0 0
  1. --[[
  2. ComputerCraft GUI library by DennouNeko
  3. Distributed under CC BY-NC-SA license:
  4. -Attribution required
  5. -Only non-commercial uses are permitted
  6. -Adaptations must be shared under same terms
  7. --]]
  8.  
  9. -- TODO: type checking for arguments and sanity checks
  10.  
  11. local expect = dofile("rom/modules/main/cc/expect.lua").expect
  12.  
  13. local gui = {}
  14.  
  15. local function isInside(elem, px, py)
  16.     local x1,y1 = elem.getPosition()
  17.     local cx,cy = elem.getSize()
  18.     local x2,y2 = x1+cx-1,y1+cy-1
  19.    
  20.     return x1 <= px and px <= x2 and y1 <= py and py <= y2
  21. end
  22.  
  23. function gui.version()
  24.     return "libGUI v1.0.2"
  25. end
  26.  
  27. -- Creates a new, raw gui element -
  28. -- a wrapper for window/terminal.
  29. -- If position and dimensions are not
  30. -- specified, it fills whole parent terminal.
  31. function gui.create(parent, x, y, cx, cy, text)
  32.     if x == nil or y == nil then
  33.         x,y = 1,1
  34.     end
  35.     if cx == nil or cy == nil then
  36.         cx,cy = parent.getSize()
  37.     end
  38.     local self = window.create(parent, x, y, cx, cy)
  39.    
  40.     self.text = text or ""
  41.     self.type = nil
  42.     self.child = {}
  43.    
  44.     function self.setText(newText)
  45.         self.text = newText or ""
  46.     end
  47.    
  48.     function self.addChild(child)
  49.         self.child[#self.child+1] = child
  50.     end
  51.    
  52.     function self.onClick(px, py)
  53.         local hit = false
  54.         for k,v in pairs(self.child) do
  55.             local dx,dy = v.getPosition()
  56.             if v.isVisible() and isInside(v, px, py) then
  57.                 hit = v.onClick(px-dx+1, py-dy+1)
  58.             end
  59.             if hit then break end
  60.         end
  61.            
  62.         --if not hit then
  63.             -- nothing to do when clicked background
  64.         --end
  65.        
  66.         return hit
  67.     end
  68.    
  69.     function self.colorSwap(newFg, newBg)
  70.         local bg = self.getBackgroundColor()
  71.         local fg = self.getTextColor()
  72.         newFg = newFg or fg
  73.         newBg = newBg or bg
  74.         self.setBackgroundColor(newBg)
  75.         self.setTextColor(newFg)
  76.         return fg, bg
  77.     end
  78.    
  79.     local _redraw = self.redraw
  80.     function self.redraw()
  81.         _redraw()
  82.        
  83.         for k,v in pairs(self.child) do
  84.             if v.isVisible() then
  85.                 v.redraw()
  86.             end
  87.         end
  88.     end
  89.    
  90.     return self
  91. end
  92.  
  93. function gui.window(parent, x, y, cx, cy, title)
  94.     local self = gui.create(parent, x, y, cx, cy, title)
  95.     self.type = "window"
  96.    
  97.     local _color_fg = colors.white
  98.     local _color_bg = colors.lightGray
  99.    
  100.     self.setBackgroundColor(_color_bg)
  101.     self.setTextColor(_color_fg)
  102.     self.clear()
  103.    
  104.     local _redraw = self.redraw
  105.     function self.redraw()
  106.         _redraw()
  107.        
  108.         -- backup current colors and set first used colors
  109.         local fg,bg = parent.colorSwap(colors.white, colors.blue)
  110.        
  111.         local title1 = tostring(self.text):sub(1,cx-1)
  112.         local fullTitle = "  " .. title1 .. string.rep(" ", cx-1 - #title1) .. "X"
  113.         parent.setCursorPos(x-1, y-1)
  114.         parent.write(fullTitle)
  115.        
  116.         for py = y,y+cy do
  117.             parent.setBackgroundColor(colors.white)
  118.             parent.setCursorPos(x-1,py)
  119.             parent.write(" ")
  120.             parent.setBackgroundColor(colors.gray)
  121.             parent.setCursorPos(x+cx,py)
  122.             parent.write(" ")
  123.         end
  124.        
  125.         parent.setCursorPos(x,y+cy)
  126.         parent.write(string.rep(" ", cx+1))
  127.        
  128.         -- restore original colors
  129.         parent.colorSwap(fg, bg)
  130.     end
  131.    
  132.     parent.addChild(self)
  133.     return self
  134. end
  135.  
  136.  
  137. function gui.button(parent, x, y, cx, cy, label, func, param)
  138.     local self = gui.create(parent, x, y, cx, cy, label)
  139.     self.type = "button"
  140.    
  141.     local _state = false
  142.     local _color_off = colors.red
  143.     local _color_on = colors.lime
  144.    
  145.     function self.setState(state)
  146.         _state = state
  147.     end
  148.    
  149.     function self.getState()
  150.         return _state
  151.     end
  152.    
  153.     function self.setColors(color_on, color_off)
  154.         _color_on = color_on or _color_on
  155.         _color_off = color_off or _color_off
  156.     end
  157.    
  158.     function self.toggle()
  159.         _state = not _state
  160.         return _state
  161.     end
  162.    
  163.     function self.redraw()
  164.         local color
  165.         if _state then
  166.             color = _color_on
  167.         else
  168.             color = _color_off
  169.         end
  170.        
  171.         local py = math.floor(cy / 2) + 1
  172.         local px = math.floor((cx - #self.text) / 2) + 1
  173.        
  174.         local fg,bg = self.colorSwap(colors.white, color)
  175.         --for ly = y,y+cy-1 do
  176.         --    temp.setCursorPos(x,ly)
  177.         --    temp.write(string.rep(" ", cx))
  178.         --end
  179.         self.clear()
  180.         self.setCursorPos(px, py)
  181.         self.write(self.text)
  182.         self.colorSwap(fg, bg)
  183.     end
  184.    
  185.     function self.onClick(px,py)
  186.         if func ~= nil then
  187.             func(self, param)
  188.         elseif doDebug then
  189.             print("No handler for button \"" .. tostring(self.text) .. "\"")
  190.         end
  191.        
  192.         return true
  193.     end
  194.    
  195.     parent.addChild(self)
  196.     return self
  197. end
  198.  
  199. function gui.progress(parent, x, y, cx, cy, isVertical, clickCallback, param)
  200.     local self = gui.create(parent, x, y, cx, cy, nil)
  201.     self.type = "progress"
  202.    
  203.     local _color_fg = colors.blue
  204.     local _color_bg = colors.black
  205.    
  206.     local _min = 0
  207.     local _max = 100
  208.     local _pos = 0
  209.    
  210.     function self.setRange(min, max)
  211.         _min = math.min(min,max)
  212.         _max = math.max(min,max)
  213.         self.setProgress(_pos)
  214.     end
  215.    
  216.     function self.setProgress(pos)
  217.         _pos = math.max(_min,math.min(_max,pos))
  218.     end
  219.    
  220.     function self.setColors(color_fg, color_bg)
  221.         _color_fg = color_fg or _color_fg
  222.         _colot_bg = color_bg or _color_bg
  223.     end
  224.    
  225.     function self.redraw()
  226.         local fg,bg = self.colorSwap(colors.white, _color_bg)
  227.        
  228.         local p = (_pos - _min) / (_max - _min)
  229.        
  230.         self.clear()
  231.        
  232.         self.setBackgroundColor(_color_fg)
  233.         -- at this point p is a value between 0 and 1
  234.         -- representing progress between 0% and 100%
  235.         if not isVertical then
  236.             -- convert it to bar width
  237.             local pw = math.floor(p * cx + 0.5)
  238.             local line = string.rep(" ", pw)
  239.             for py = 1,cy do
  240.                 self.setCursorPos(1,py)
  241.                 self.write(line)
  242.             end
  243.         else
  244.             -- convert it to bar height
  245.             p = math.floor((1 - p) * cy + 0.5) + 1
  246.             local line = string.rep(" ", cx)
  247.             for py = p,cy do
  248.                 self.setCursorPos(1,py)
  249.                 self.write(line)
  250.             end
  251.         end
  252.        
  253.         self.colorSwap(fg, bg)
  254.     end
  255.    
  256.     function self.onClick(px, py)
  257.         if clickCallback == nil then
  258.             return false
  259.         end
  260.        
  261.         local pos = 0
  262.        
  263.         if not isVertical then
  264.             pos = (px - 1) / (cx - 1)
  265.         else
  266.             pos = 1 - (py - 1) / (cy - 1)
  267.         end
  268.         pos = math.floor(pos * (_max - _min))
  269.        
  270.         clickCallback(self, param, pos)
  271.        
  272.         return true
  273.     end
  274.    
  275.     parent.addChild(self)
  276.     return self
  277. end
  278.  
  279. function gui.label(parent, x, y, cx, cy, text, align)
  280.     local self = gui.create(parent, x, y, cx, cy)
  281.     self.type = "label"
  282.    
  283.     text = text or ""
  284.     align = align or "TL"
  285.    
  286.     local _color_fg = colors.black
  287.     local _color_bg = colors.lightGray
  288.    
  289.     function self.setText(_text, _align)
  290.         text = _text or ""
  291.         align = _align or align
  292.     end
  293.    
  294.     function self.setColors(color_fg, color_bg)
  295.         _color_fg = color_fg or _color_fg
  296.         _color_bg = color_bg or _color_bg
  297.     end
  298.    
  299.     function self.redraw()
  300.         local valign = align:sub(1,1)
  301.         local halign = align:sub(2,2)
  302.        
  303.         local px,py
  304.        
  305.         if halign == "L" or halign == "l" then
  306.             px = 1
  307.         elseif halign == "R" or halign == "r" then
  308.             px = cx - #text + 1
  309.         elseif halign == "C" or halign == "c" then
  310.             px = math.floor((cx - #text) / 2) + 1
  311.         end
  312.        
  313.         if valign == "T" or valign == "t" then
  314.             py = 1
  315.         elseif valign == "B" or valign == "b" then
  316.             py = cy
  317.         elseif valign == "C" or valign == "c" then
  318.             py = math.floor(cx / 2) + 1
  319.         end
  320.        
  321.         local fg,bg = self.colorSwap(_color_fg, _color_bg)
  322.        
  323.         self.clear()
  324.         self.setCursorPos(px, py)
  325.         self.write(text)
  326.        
  327.         self.colorSwap(fg, bg)
  328.     end
  329.    
  330.     parent.addChild(self)
  331.     return self
  332. end
  333.  
  334. return gui
  335.  
Advertisement
Add Comment
Please, Sign In to add comment