Kingdaro

Immediate-Mode GUI for ComputerCraft

Dec 22nd, 2013
316
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 4.79 KB | None | 0 0
  1. local drawFuncs = {}
  2. local maxid = 0
  3.  
  4. local defaults = {
  5.     label = {
  6.         bgColor = colors.black;
  7.         textColor = colors.white;
  8.     };
  9.     button = {
  10.         bgColor = colors.blue;
  11.         textColor = colors.white;
  12.         padding = {2, 1};
  13.     };
  14.     slider = {
  15.         orientation = 'horizontal';
  16.         length = 20;
  17.         bgColor = colors.gray;
  18.         fgColor = colors.blue;
  19.         min = 0;
  20.         max = 1;
  21.     };
  22. }
  23.  
  24. local mouse = {
  25.     clicked = false;
  26.     dragged = false;
  27.     focus = nil;
  28.     x = 1;
  29.     y = 1;
  30. }
  31.  
  32. local function copy(source, from)
  33.     for k,v in pairs(from) do
  34.         if type(v) == 'table' then
  35.             copy(source[k], v)
  36.         else
  37.             source[k] = v
  38.         end
  39.     end
  40. end
  41.  
  42. local function genid()
  43.     maxid = maxid + 1
  44.     return maxid
  45. end
  46.  
  47. local function checkArea(mx, my, x, y, w, h)
  48.     return mx >= x and mx < x + w and my >= y and my < y + h
  49. end
  50.  
  51. local function checkClick(...)
  52.     return mouse.clicked and checkArea(mouse.x, mouse.y, ...)
  53. end
  54.  
  55. local function checkDrag(...)
  56.     return mouse.dragged and checkArea(mouse.x, mouse.y, ...)
  57. end
  58.  
  59. local function dimensions(text)
  60.     return #text + (defaults.button.padding[1] or 2) * 2,
  61.         1 + (defaults.button.padding[2] or 1) * 2
  62. end
  63.  
  64. local function rect(x, y, width, height, color)
  65.     local fill = string.rep(' ', width)
  66.     if color then term.setBackgroundColor(color) end
  67.     for i=1, height do
  68.         term.setCursorPos(x, y + (i - 1))
  69.         term.write(fill)
  70.     end
  71. end
  72.  
  73. local function checkInfo(info)
  74.     if type(info) ~= 'table' then
  75.         error("Bad argument: table expected", 3)
  76.     end
  77. end
  78.  
  79. local function drawButton(info)
  80.     rect(info.x, info.y, info.width, info.height,
  81.         info.bgColor or (defaults.button and defaults.button.bgColor))
  82.  
  83.     if info.text then
  84.         textColor = info.textColor or defaults.button.textColor
  85.         if textColor then term.setTextColor(textColor) end
  86.         term.setCursorPos(
  87.             info.x + math.ceil(info.width/2) - math.ceil(#info.text/2),
  88.             info.y + math.ceil(info.height/2) - 1)
  89.         term.write(tostring(info.text))
  90.     end
  91. end
  92.  
  93. local function drawSlider(info, width, height)
  94.     rect(info.x, info.y, width, height, info.bgColor)
  95.  
  96.     -- i hate this math
  97.     -- i really do
  98.     if info.orientation == 'horizontal' then
  99.         width = math.max(math.ceil(width * ((info.value - info.min) / (info.max - info.min))), 1)
  100.     else
  101.         height = math.max(math.ceil(height * ((info.value - info.min) / (info.max - info.min))), 1)
  102.     end
  103.  
  104.     rect(info.x, info.y, width, height, info.fgColor)
  105. end
  106.  
  107.  
  108. function setDefaults(t)
  109.     copy(defaults, t)
  110. end
  111.  
  112. function clear(color)
  113.     if color then term.setBackgroundColor(color) end
  114.     term.clear()
  115. end
  116.  
  117. function label(info)
  118.     checkInfo(info)
  119.     register(function()
  120.         bgColor = info.bgColor or defaults.label.bgColor
  121.         textColor = info.textColor or defaults.label.textColor
  122.         if bgColor then term.setBackgroundColor(bgColor) end
  123.         if textColor then term.setTextColor(textColor) end
  124.  
  125.         term.setCursorPos(info.x, info.y)
  126.         term.write(info.text)
  127.     end)
  128. end
  129.  
  130. function button(info)
  131.     checkInfo(info)
  132.  
  133.     local tw, th = dimensions(info.text)
  134.     info.width = info.width or tw
  135.     info.height = info.height or th
  136.     info.bgColor = info.bgColor or defaults.button.bgColor
  137.     info.textColor = info.textColor or defaults.button.textColor
  138.  
  139.     local clicked = checkClick(info.x, info.y, info.width, info.height)
  140.     if clicked then
  141.         mouse.clicked = false -- to make sure overlapping items don't receive clicks
  142.     end
  143.  
  144.     info.text = tostring(info.text)
  145.     register(drawButton, info)
  146.  
  147.     return clicked
  148. end
  149.  
  150. function slider(info)
  151.     checkInfo(info)
  152.  
  153.     setmetatable(info, { __index = defaults.slider })
  154.     info.value = info.value or (info.max - info.min) / 2
  155.  
  156.     local width, height = info.length, 1
  157.     if info.orientation == 'vertical' then
  158.         width, height = height, width
  159.     end
  160.  
  161.     local id = genid()
  162.     local clicked = checkClick(info.x, info.y, width, height)
  163.     local changed = false
  164.  
  165.     if clicked then
  166.         mouse.clicked = false
  167.         mouse.focus = id
  168.     end
  169.  
  170.     if clicked or mouse.dragged and mouse.focus == id then
  171.         local dist = (info.orientation == 'horizontal' and mouse.x - info.x or mouse.y - info.y)
  172.         local ratio = math.min(dist / (info.length - 1), 1)
  173.         info.value = ratio * (info.max - info.min) + info.min
  174.         changed = true
  175.     end
  176.  
  177.     register(drawSlider, info, width, height)
  178.     return changed
  179. end
  180.  
  181.  
  182. function register(func, ...)
  183.     table.insert(drawFuncs, {func, ...})
  184. end
  185.  
  186. function draw()
  187.     for i=1, #drawFuncs do
  188.         local func, params = table.remove(drawFuncs[i], 1), drawFuncs[i]
  189.         func(unpack(params))
  190.     end
  191.     drawFuncs = {}
  192. end
  193.  
  194.  
  195. function pullEvent()
  196.     mouse.clicked = false
  197.     mouse.dragged = false
  198.     maxid = 0
  199.  
  200.     local params = {os.pullEvent()}
  201.     local event = table.remove(params, 1)
  202.  
  203.     if event:match 'mouse' then
  204.         mouse.x = params[2]
  205.         mouse.y = params[3]
  206.         if event == 'mouse_click' then
  207.             mouse.clicked = true
  208.         elseif event == 'mouse_drag' then
  209.             mouse.dragged = true
  210.         end
  211.     end
  212.     return event, unpack(params)
  213. end
Advertisement
Add Comment
Please, Sign In to add comment