Advertisement
tahg

gui.lua

Aug 21st, 2014
298
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 12.61 KB | None | 0 0
  1. require "system"
  2.  
  3. class "Control" {
  4.  
  5. unique = 1,
  6.  
  7. public = [[{
  8. init = function(parent)
  9.   setPos(0, 0)
  10.   setSize(0, 0)
  11.   setVisible(true)
  12.   setName("Control_"..Control.unique)
  13.   Control.unique = Control.unique + 1
  14.   __parent = parent
  15. end,
  16.  
  17. setPos = function(x, y)
  18.   this.x = x
  19.   this.y = y
  20.   return this
  21. end,
  22.  
  23. getPos = function()
  24.   return x, y
  25. end,
  26.  
  27. getAbsPos = function()
  28.   local x, y = 0, 0
  29.   if __parent then
  30.     x, y = __parent.getAbsPos()
  31.   end
  32.   x = x + this.x
  33.   y = y + this.y
  34.   return x, y
  35. end,
  36.  
  37. setSize = function(w, h)
  38.   width = w
  39.   height = h
  40.   return this
  41. end,
  42.  
  43. getSize = function()
  44.   return width, height
  45. end,
  46.  
  47. getMinSize = function()
  48.   return 1, 1
  49. end,
  50.  
  51. setName = function(name)
  52.   this.name = name
  53.   return this
  54. end,
  55.  
  56. setFGColor = function(color)
  57.   fgc = color
  58.   return this
  59. end,
  60.  
  61. setBGColor = function(color)
  62.   bgc = color
  63.   return this
  64. end,
  65.  
  66. click = function(x, y)
  67. end,
  68.  
  69. onClick = function()
  70. end,
  71.  
  72. setVisible = function(visible)
  73.   this.visible = visible
  74.   return this
  75. end,
  76.  
  77. isVisible = function()
  78.   return visible
  79. end,
  80.  
  81. draw = function()
  82.   if not isVisible() then return nil end
  83.   local device = getDevice()
  84.   if device then
  85.     local l, t = getAbsPos()
  86.     local w, h = getSize()
  87.     local r, b = l + w - 1, t + h - 1
  88.     local dx, dy = device.getSize()
  89.     --    print("Drawing control at ("..l..","..t..")")
  90.     if l < 1 then l = 1 end
  91.     if t < 1 then t = 1 end
  92.     if r > dx then r = dx end
  93.     if b > dy then b = dy end
  94.     if bgc then
  95.       if device.setBackgroundColor then
  96.         device.setBackgroundColor(bgc)
  97.       end
  98.       for row = t, b do
  99.         device.setCursorPos(l, row)
  100.         for col = l, r do
  101.           device.write(" ")
  102.         end
  103.       end
  104.     end
  105.   end
  106.   return device
  107. end,
  108.  
  109. getDevice = function()
  110.   if __parent then
  111.     return __parent.getDevice()
  112.   else return nil
  113.   end
  114. end,
  115.  
  116. contains = function(x, y)
  117.   --  print(type(x))
  118.   --  print(type(y))
  119.   return x >= this.x and x < this.x + width and
  120.   y >= this.y and y < this.y + height
  121. end
  122. }]]
  123. }
  124.  
  125. class "Label" "Control" {
  126.  
  127. public = [[{
  128. init = function()
  129.   setAlign("center").setVAlign(center).setText("")
  130. end,
  131.  
  132. getMinSize = function()
  133.   return #text, 1
  134. end,
  135.  
  136. setText = function(text)
  137.   this.text = text
  138.   return this
  139. end,
  140.  
  141. setAlign = function(align)
  142.   this.align = align
  143.   return this
  144. end,
  145.  
  146. setVAlign = function(align)
  147.   this.valign = align
  148.   return this
  149. end,
  150.  
  151. draw = function()
  152.   local device = super.draw()
  153.   if not device then return end
  154.   --  print("drawing label "..self.name)
  155.   local x, y = getAbsPos()
  156.   local text = text
  157.   local slackx = width - #text
  158.   local slacky = height - 1
  159.   if align == "center" then
  160.     x = x + slackx / 2
  161.   elseif align == "right" then
  162.     x = x + slackx
  163.   end
  164.   if valign == "center" then
  165.     y = y + slacky / 2
  166.   elseif valign == "bottom" then
  167.     y = y + slacky
  168.   end
  169.   --  print("Displaying text '"..text.."' at ("..x..", "..y..")")
  170.   device.setCursorPos(x, y)
  171.   device.setTextColor(self.fgc)
  172.   device.write(text)
  173.   return device
  174. end
  175. }]]
  176. }
  177.  
  178. class "Button" "Label" {
  179.  
  180. public = [[{
  181.  
  182. init = function()
  183.   state = false
  184. end,
  185.  
  186. setActive = function(state)
  187.   if group then group.reset() end
  188.   this.state = state
  189.   update()
  190.   return this
  191. end,
  192.  
  193. setActiveColor = function(color)
  194.   hlc = color
  195.   update()
  196.   return this
  197. end,
  198.  
  199. setInactiveColor = function(color)
  200.   iac = color
  201.   update()
  202.   return this
  203. end,
  204.  
  205. setToggle = function(toggle)
  206.   this.toggle = toggle
  207.   return this
  208. end,
  209.  
  210. update = function()
  211.   bgc = state and hlc or iac
  212. end,
  213.  
  214. draw = function()
  215.   update()
  216.   super.draw()
  217. end,
  218.  
  219. click = function()
  220.   if toggle then
  221.     setActive(not state)
  222.     else setActive(true)
  223.   end
  224.   draw()
  225.   os.sleep(.15)
  226.   onClick()
  227.   if not toggle then setActive(false) end
  228.   draw()
  229.   os.sleep(.15)
  230. end
  231. }]]
  232. }
  233.  
  234. class "ButtonGroup"
  235.  
  236. public = [[{
  237.  
  238. init = function()
  239.   clear()
  240. end,
  241.  
  242. add = function(button)
  243.   if button.instanceof(Button) then
  244.     table.insert(buttons, button)
  245.     button.group = this
  246.     else print("Not a button")
  247.   end
  248. end,
  249.  
  250. clear = function()
  251.   buttons = {}
  252. end,
  253.  
  254. reset = function()
  255.   for i, b in ipairs(buttons) do
  256.     b.state = false
  257.   end
  258. end
  259. }]]
  260. }
  261.  
  262. class "Container" "Control" {
  263.  
  264. public = [[{
  265.  
  266. clear = function()
  267.   controls = {}
  268.   controlsByName = {}
  269. end,
  270.  
  271. init = function()
  272.   clear()
  273. end,
  274.  
  275. add = function(control)
  276.   table.insert(controls, control)
  277.   --  print(control.name)
  278.   controlsByName[control.name] = control
  279.   control.__parent = this
  280.   control.__idx = #control
  281. end,
  282.  
  283. find = function(name)
  284.   return controlsByName[name]
  285. end,
  286.  
  287. findIndex = function(control)
  288.   if type(control) == "string" then
  289.     control = find(control)
  290.   end
  291.   if control.__parent ~= this then return nil end
  292.   if control.__idx and controls[control.__idx] == control then
  293.     return control.__idx
  294.   end
  295.   for i = 1, #controls do
  296.     if controls[i] == control then
  297.       control.__idx = i
  298.       return i
  299.     end
  300.   end
  301.   return nil
  302. end,
  303.  
  304. moveUp = function(control)
  305.   idx = findIndex(control)
  306.   if not idx or idx >= #controls then return nil end
  307.   controls[idx] = controls[idx+1]
  308.   controls[idx].__idx = idx
  309.   controls[idx+1] = control
  310.   control.__idx = idx+1
  311. end,
  312.  
  313. moveDown = function(control)
  314.   idx = findIndex(control)
  315.   if not idx or idx <= 1 then return nil end
  316.   controls[idx] = controls[idx-1]
  317.   controls[idx]._idx = idx
  318.   controls[idx-1] = control
  319.   control.__idx = idx-1
  320. end,
  321.  
  322. moveTop = function(control)
  323.   while moveUp(control) do end
  324. end,
  325.  
  326. moveBottom = function(control)
  327.   while moveDown(control) do end
  328. end,
  329.  
  330. addButton = function(name, text, func, param, x, y, w, h)
  331.   b = new "Button"()
  332.   b.name = name
  333.   b.setText(text)
  334.   b.setPos(x, y)
  335.   b.setSize(w, h)
  336.   b.setAction(func, param)
  337.   b.setActive(false)
  338.   add(b)
  339. end,
  340.  
  341. addLabel = function(name, text, x, y, w, h)
  342.   l = new "Label"()
  343.   l.name = name
  344.   l:setText(text)
  345.   l:setPos(x, y)
  346.   l:setSize(w, h)
  347.   self:add(l)
  348. end,
  349.  
  350. draw = function()
  351.   local device = super.draw()
  352.   if not device then return end
  353.   for k, v in ipairs(controls) do
  354.     v.draw()
  355.   end
  356.   return device
  357. end,
  358.  
  359. click = function(x, y)
  360.   print("Clicked ("..x..", "..y..")")
  361.  
  362.   for i = #controls, 1, -1 do
  363.     local c = controls[i]
  364.     if c.isVisible() and c.contains(x, y) then
  365.       c.click(x - c.x, y - c.y)
  366.       return
  367.     end
  368.   end
  369.   onClick(x, y)
  370. end
  371. }]]
  372. }
  373.  
  374. class "Screen" "Container"
  375.  
  376. public = [[{
  377.  
  378. init = function()
  379.   setPos(1,1)
  380. end,
  381.  
  382. setDevice = function(device)
  383.   this.device = device
  384.   if device then
  385.     setSize(device.getSize())
  386.     device.setScreen(this)
  387.   end
  388.   return this
  389. end,
  390.  
  391. getDevice = function()
  392.   return device
  393. end,
  394.  
  395. draw = function()
  396.   if device then
  397.     device.clear()
  398.     return super.draw()
  399.   end
  400. end,
  401.  
  402. click = function(x, y)
  403.   sx, sy = getAbsPos()
  404.   super.click(x - sx, y - sy)
  405. end
  406. }]]
  407. }
  408.  
  409. class "Scrollbar" "Control"
  410.  
  411. public = [[{
  412.  
  413. init = function()
  414.   thumb = new "Control"()
  415.   thumb.__parent = this
  416.   pos = 0
  417.   max = 0
  418. end,
  419.  
  420. setBounds = function(min, max)
  421.   pos = 0
  422.   this.min = min
  423.   this.max = max
  424.   return this
  425. end,
  426.  
  427. setProgress = function(value)
  428.   if value >= min and value <= max then
  429.     pos = value
  430.   end
  431.   return this
  432. end,
  433.  
  434. getProgress = function()
  435.   return math.floor(pos + 0.5)
  436. end,
  437.  
  438. setPercent = function(value)
  439.   local range = max - min
  440.   if range > 0 and value >= 0 and value <= 100 then
  441.     pos = min + range * value
  442.   end
  443.   return this
  444. end,
  445.  
  446. setType = function(value)
  447.   type = value
  448.   return this
  449. end,
  450.  
  451. draw = function()
  452.   --  print(self.__parent)
  453.  
  454.   device = super.draw()
  455.   if not device then return end
  456.   if width >= 1 and height >= 1 then
  457.     --    print("Drawing scrollbar at ("..x..","..y..")")
  458.     --    print("Min "..min.." Max "..max)
  459.     if max > min then
  460.       if type == "horizontal" then
  461.         thumb.setSize(1, height)
  462.         thumb.setPos((pos - min) / (max - min) * (width-1), 0)
  463.       else
  464.         thumb.setSize(self.width, 1)
  465.         thumb.setPos(0, (pos - min) / (max - min) * (height-1))
  466.       end
  467.       --      print(self.thumb.name)
  468.       --      print(self.thumb.isVisible())
  469.       thumb.setBGColor(colors.blue)
  470.       local tx, ty = thumb.getAbsPos()
  471.       --      print("Drawing thumb at ("..tx..","..ty..")")
  472.      
  473.       thumb.draw()
  474.     end
  475.   end
  476.   return device
  477. end,
  478.  
  479. click = function(x, y)
  480.   if type == horizontal then
  481.     setPercent((x - this.x) / (width - 1))
  482.   else
  483.     setPercent((y - this.y) / (height - 1))
  484.   end
  485.   --  print("Set scrollbar to "..pos)
  486. end
  487. }]]
  488. }
  489.  
  490. class "Grid" "Container"
  491.  
  492. public = [[{
  493.  
  494. init = function()
  495.   hscroll = new "Scrollbar"(this)
  496.   .setFGColor(colors.gray)
  497.   .setBGColor(colors.lightGray)
  498.   .setType("horizontal")
  499.   vscroll = new "Scrollbar"(self)
  500.   .setFGColor(colors.gray)
  501.   .setBGColor(colors.lightGray)
  502.   .setType("vertical")
  503.   rows, cols = 0, 0
  504. end,
  505.  
  506. setMargins = function(ml, mt, mr, mb)
  507.   this.ml, this.mt, this.mr, this.mb = ml, mt, mr, mb
  508.   return this
  509. end,
  510.  
  511. setHGap = function(gap)
  512.   hgap = gap
  513.   return this
  514. end,
  515.  
  516. setVGap = function(gap)
  517.   vgap = gap
  518.   return this
  519. end,
  520.  
  521. setRows = function(rows)
  522.   this.rows = rows
  523.   return this
  524. end,
  525.  
  526. setCols = function(cols)
  527.   this.cols = cols
  528.   return this
  529. end,
  530.  
  531. --"horizontal": will lay out by columns
  532. --"vertical": will lay out by rows
  533. setDirection =function(dir)
  534.   this.dir = dir
  535.   return this
  536. end,
  537.  
  538. doLayout = function()
  539.   init()
  540.   local minx, miny = 0, 0
  541.   local ex, ey = 1, 1
  542.   for k, v in ipairs(controls) do
  543.     local w, h = v.getMinSize()
  544.     if w > minx then minx = w end
  545.     if h > miny then miny = h end
  546.   end
  547.   vcols = math.floor((width - ml - mr - ex + hgap) / (minx + hgap))
  548.   vcols2 = math.floor((width - ml - mr + hgap) / (minx + hgap))
  549.   vrows = math.floor((height - mt - mb - ey + vgap) / (miny + vgap))
  550.   vrows2 = math.floor((height - mt - mb + vgap) / (miny + vgap))
  551.   if rows < 1 and cols >= 1 then
  552.     rows = math.ceil(#controls / cols)
  553.   elseif cols < 1 and rows >=1 then
  554.     cols = math.ceil(#controls / rows)
  555.   else
  556.     if dir == "vertical" then
  557.       if cols < 1 then
  558.         vrows = vrows2
  559.         ey = 0
  560.         if #controls <= vrows * vcols2 then
  561.           vcols = vcols2
  562.           ex = 0
  563.         end
  564.         cols = vcols
  565.       end
  566.       rows = math.ceil(#controls / cols)
  567.     else
  568.       if rows < 1 then
  569.         vcols = vcols2
  570.         ex = 0
  571.         if #controls <= vcols * vrows2 then
  572.           vrows = vrows2
  573.           ey = 0
  574.         end
  575.         rows = vrows
  576.       end
  577.       cols = math.ceil(#controls / rows)
  578.     end
  579.   end
  580.   if rows > vrows then
  581.     vscroll.setBounds(0, rows - vrows)
  582.     vscroll.setVisible(true)
  583.   else
  584.     vscroll.setBounds(0, 0)
  585.     vscroll.setVisible(false)
  586.   end
  587.   if cols > vcols then
  588.     hscroll.setBounds(0, cols - vcols)
  589.     hscroll.setVisible(true)
  590.   else
  591.     hscroll.setBounds(0, 0)
  592.     hscroll.setVisible(false)
  593.   end
  594.   vscroll.setPos(width - 1 - mr, mt)
  595.   if hscroll.isVisible() then
  596.     vscroll.setSize(1, height - mt - mb - 1)
  597.   else vscroll.setSize(1, height - mt - mb)
  598.   end
  599.   hscroll.setPos(ml, height - 1 - mb)
  600.   if vscroll.isVisible() then
  601.     hscroll.setSize(width - ml - mr - 1, 1)
  602.   else hscroll.setSize(width - ml - mr, 1)
  603.   end
  604.   cwidth = math.floor((width - ml - mr - ex + hgap) / vcols) - hgap
  605.   cheight = math.floor((height - mt - mb - ey + vgap) / vrows) - vgap
  606.   print(cwidth)
  607.   print(cheight)
  608.   for k, v in ipairs(controls) do
  609.     v.setSize(cwidth, cheight)
  610.   end
  611. end,
  612.  
  613. draw = function()
  614.   local voff = vscroll.getProgress()
  615.   local hoff = hscroll.getProgress()
  616.   if dir == "vertical" then
  617.     local y = mt
  618.     for row = 0, vrows - 1 do
  619.       local x = ml
  620.       for col = 0, vcols - 1 do
  621.         local index = (row + voff) * cols + col + hoff + 1
  622.         local control = controls[index]
  623.         if control then
  624.           control.setPos(x, y)
  625.           control.draw()
  626.         end
  627.         x = x + cwidth + hgap
  628.       end
  629.       y = y + cheight + vgap
  630.     end
  631.   else
  632.     local x = ml
  633.     for col = 0, vcols - 1 do
  634.       local y = mt
  635.       for row = 0, vrows - 1 do
  636.         local index = (col + hoff) * rows + row + voff + 1
  637.         local control = controls[index]
  638.         if control then
  639.           control.setPos(x, y)
  640.           control.draw()
  641.         end
  642.         y = y + cheight + vgap
  643.       end
  644.       x = x + cwidth + hgap
  645.     end
  646.   end
  647.   vscroll.draw()
  648.   hscroll.draw()
  649. end,
  650.  
  651. click = function(x, y)
  652.   if vscroll.isVisible() and vscroll.contains(x, y) then
  653.     vscroll.click(x, y)
  654.   elseif hscroll.isVisible() and hscroll.contains(x, y) then
  655.     hscroll.click(x, y)
  656.   else super.click(x, y)
  657.   end
  658. end
  659. }]]
  660. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement