Advertisement
Morverzhus

CC Rylib

Jan 31st, 2015
223
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 18.17 KB | None | 0 0
  1. -- Class Hierarchy
  2. --  - Renderable
  3. --      - ProgressBar
  4. --          - VerticalProgressBar
  5. --          - HorizontalProgressBar
  6. --      - Button
  7. --          - PushButton
  8. --          - ToggleButton
  9.  
  10. -- Renderable
  11. --   Variables:
  12. --     x, y, width, height, foreground, background, border
  13. --   Functions:
  14. --     DrawBorder()
  15. --     Update()
  16. --     IsSelected()
  17. --     SetHandle()
  18.  
  19. local Renderable = (function()
  20.     local r = {}; r.__index = r
  21.  
  22.     function r:Update()
  23.         if (self.Draw) then
  24.             self:Draw()
  25.         end
  26.     end
  27.  
  28.     function r:DrawBorder()
  29.         local p1, p2, p3, p4 = self.p1, self.p2, self.p3, self.p4
  30.  
  31.         if (self.border) then
  32.             paintutils.drawLine(p1.x, p1.y, p2.x, p2.y, self.border)
  33.             paintutils.drawLine(p2.x, p2.y, p3.x, p3.y, self.border)
  34.             paintutils.drawLine(p3.x, p3.y, p4.x, p4.y, self.border)
  35.             paintutils.drawLine(p4.x, p4.y, p1.x, p1.y, self.border)
  36.         end
  37.     end
  38.  
  39.     function r:SetHandle(handle)
  40.         self.handle = handle
  41.     end
  42.  
  43.     function r:IsSelected(x, y)
  44.         local xMin, xMax = self.x, self.x + self.width
  45.         local yMin, yMax = self.y, self.y + self.height
  46.  
  47.         local xValid = x >= xMin and x <= xMax
  48.         local yValid = y >= yMin and y <= yMax
  49.  
  50.         return xValid and yValid
  51.     end
  52.  
  53.     local mt = {
  54.         __call = function(self, x, y, width, height, foreground, background, border, funcSelect)
  55.             assert(type(x) == 'number', 'No coordinate for x provided')
  56.             assert(type(y) == 'number', 'No coordinate for y provided')
  57.  
  58.             local renderable = {
  59.                 x = x,
  60.                 y = y,
  61.                 width = width,
  62.                 height = height,
  63.                 foreground = foreground,
  64.                 background = background,
  65.                 border = border,
  66.                 enabled = true,
  67.                 p1 = {x = x, y = y},
  68.                 p2 = {x = x + width, y = y},
  69.                 p3 = {x = x + width, y = y + height},
  70.                 p4 = {x = x, y = y + height},
  71.                 Select = funcSelect or function() print("No function bound to select") end,
  72.             }
  73.  
  74.             setmetatable(renderable, r)
  75.  
  76.             return renderable
  77.         end
  78.     }
  79.  
  80.     setmetatable(r, mt)
  81.  
  82.     return r
  83. end) ()
  84.  
  85. -- ProgressBar
  86. --   Variables:
  87. --     Base: Renderable
  88. --     New: progress
  89. local ProgressBar = (function(baseClass)
  90.     local pb = {}; pb.__index = pb
  91.  
  92.     local mt = {
  93.         __call = function(self, x, y, width, height, foreground, background, border, funcSelect)
  94.             local bar = baseClass(x, y, width, height, foreground, background, border, funcSelect)
  95.  
  96.             bar.progress = 0
  97.  
  98.             setmetatable(bar, pb)
  99.  
  100.             return bar
  101.         end,
  102.  
  103.         __index = baseClass,
  104.     }
  105.  
  106.     setmetatable(pb, mt)
  107.  
  108.     return pb
  109. end) (Renderable)
  110.  
  111. -- Button
  112. --   Variables:
  113. --     Base: Renderable
  114. --     New: handle, text
  115. --   Functions:
  116. --     DrawFill,
  117. --     Draw,
  118. local Button = (function(baseClass)
  119.     local b = {}; b.__index = b
  120.  
  121.     -- Description: Draws the inner part of the button
  122.     -- Returns: nil
  123.     function b:DrawFill()
  124.         local fillColour = (self.toggled == true and self.foreground or self.background)
  125.  
  126.         for x = self.x, self.x + self.width - 1 do
  127.             for y = self.y, self.y + self.height - 1 do
  128.                 paintutils.drawPixel(x, y, fillColour)
  129.             end
  130.         end
  131.     end
  132.  
  133.     -- Description: Draws the button
  134.     -- Returns: nil
  135.     function b:Draw()
  136.         self:DrawFill()
  137.         self:DrawBorder()
  138.  
  139.         -- Set background for text
  140.         self.text.background = self.toggled and self.foreground or self.background
  141.  
  142.         -- Draw text on button
  143.         self.text:Draw()
  144.     end
  145.  
  146.     local mt = {
  147.         __call = function(self, x, y, width, height, handle, text, foreground, background, border, funcSelect)
  148.             local button = baseClass(x, y, width, height, foreground, background, border, funcSelect)
  149.  
  150.             button.handle = handle
  151.             button.text = text
  152.             button.toggled = false
  153.  
  154.             setmetatable(button, b)
  155.  
  156.             return button
  157.         end,
  158.  
  159.         __index = baseClass,
  160.     }
  161.  
  162.     setmetatable(b, mt)
  163.  
  164.     return b
  165. end) (Renderable)
  166.  
  167. VerticalProgressBar = (function (baseClass)
  168.     local vpb = {}; vpb.__index = vpb
  169.  
  170.     function vpb:Draw()
  171.         -- Calculate width for background and foreground
  172.         local bHeight = math.abs(self.height * ((self.progress - 100) / 100))
  173.         local fHeight = math.abs(self.height * (self.progress / 100))
  174.  
  175.         -- Draw background
  176.         for i = self.x, self.x + self.width - 1 do
  177.             for j = self.y, self.y + bHeight - 1 do
  178.                 paintutils.drawPixel(i, j, self.background)
  179.             end
  180.         end
  181.  
  182.         -- Draw foreground
  183.         for i = self.x, self.x + self.width - 1 do
  184.             for j = self.y + bHeight, self.y + bHeight + fHeight - 1 do
  185.                 paintutils.drawPixel(i, j, self.foreground)
  186.             end
  187.         end
  188.  
  189.         self:DrawBorder()
  190.     end
  191.  
  192.     local mt = {
  193.         __call = function(self, x, y, width, height, foreground, background, border, funcSelect)
  194.             local bar = baseClass(x, y, width, height, foreground, background, border, funcSelect)
  195.  
  196.             setmetatable(bar, vpb)
  197.  
  198.             return bar
  199.         end,
  200.  
  201.         __index = baseClass
  202.     }
  203.  
  204.     setmetatable(vpb, mt)
  205.  
  206.     return vpb
  207. end) (ProgressBar)
  208.  
  209. HorizontalProgressBar = (function(baseClass)
  210.     local hpb = {}; hpb.__index = hpb
  211.  
  212.     function hpb:Draw()
  213.         -- Calculate width for background and foreground
  214.         local bWidth = math.abs(self.width * ((self.progress - 100) / 100))
  215.         local fWidth = math.abs(self.width * (self.progress / 100))
  216.  
  217.         -- Draw background
  218.         for i = self.x + fWidth, self.x + fWidth + bWidth - 1 do
  219.             for j = self.y, self.y + self.height - 1 do
  220.                 paintutils.drawPixel(i, j, self.background)
  221.             end
  222.         end
  223.  
  224.         -- Draw foreground
  225.         for i = self.x, self.x + fWidth - 1 do
  226.             for j = self.y, self.y + self.height - 1 do
  227.                 paintutils.drawPixel(i, j, self.foreground)
  228.             end
  229.         end
  230.  
  231.         self:DrawBorder()
  232.     end
  233.  
  234.     local mt = {
  235.         __call = function(self, x, y, width, height, foreground, background, border, funcSelect)
  236.             local bar = baseClass(x, y, width, height, foreground, background, border, funcSelect)
  237.  
  238.             setmetatable(bar, hpb)
  239.  
  240.             return bar
  241.         end,
  242.  
  243.         __index = baseClass
  244.     }
  245.  
  246.     setmetatable(hpb, mt)
  247.  
  248.     return hpb
  249. end) (ProgressBar)
  250.  
  251. Text = (function(baseClass)
  252.     local t = {}; t.__index = t
  253.  
  254.     function t:Centre(w, h)
  255.         if (w and h) then
  256.             return math.floor((w / 2) - (#self.text / 2)), math.floor(h / 2)
  257.         else
  258.             return 0, 0
  259.         end
  260.     end
  261.  
  262.     function t:Write(x, y, w, h)
  263.         if (term) then
  264.             local modX, modY = self:Centre(w, h)
  265.  
  266.             if (self.background) then
  267.                 term.setBackgroundColor(self.background)
  268.             end
  269.  
  270.             term.setTextColor(self.foreground)
  271.             term.setCursorPos(x + modX, y + modY)
  272.             term.write(self.text)
  273.  
  274.             -- Reset
  275.             term.setTextColor(colors.white)
  276.             term.setCursorPos(0, 0)
  277.         end
  278.     end
  279.  
  280.     function t:Draw()
  281.         self:Write(self.x, self.y, self.width, self.height)
  282.     end
  283.  
  284.     local mt = {
  285.         __call = function(self, text, foreground, background, x, y, width, height)
  286.             assert(type(text) == 'string', 'No text provided')
  287.  
  288.             local w = width or #text
  289.             local h = height or 1
  290.  
  291.             local tInstance = baseClass(x, y, w, h, foreground or colors.white, background or colors.black, nil)
  292.  
  293.             -- Child class member
  294.             tInstance.text = text
  295.  
  296.             setmetatable(tInstance, t)
  297.  
  298.             return tInstance
  299.         end,
  300.  
  301.         __index = baseClass,
  302.     }
  303.  
  304.     setmetatable(t, mt)
  305.  
  306.     return t
  307. end) (Renderable)
  308.  
  309. PushButton = (function(baseClass)
  310.     local pb = {}; pb.__index = pb
  311.  
  312.     function pb:Select()
  313.         self.toggled = true
  314.  
  315.         if (self.handle) then
  316.             self.handle(self)
  317.         end
  318.  
  319.         self.timer = os.startTimer(.3)
  320.     end
  321.  
  322.     function pb:Handle(timer)
  323.         if (self.timer == timer) then
  324.             self.toggled = false
  325.         end
  326.     end
  327.  
  328.     local mt = {
  329.         __call = function(self, x, y, width, height, handle, text, foreground, background, border)
  330.             local textObj = Text(text, colors.white, background, x, y, width, height)
  331.             local pushButton = baseClass(x, y, width, height, handle, textObj, foreground, background, border, pb.Select)
  332.  
  333.             setmetatable(pushButton, pb)
  334.  
  335.             return pushButton
  336.         end,
  337.  
  338.         __index = baseClass,
  339.     }
  340.  
  341.     setmetatable(pb, mt)
  342.  
  343.     return pb
  344. end) (Button)
  345.  
  346. ToggleButton = (function(baseClass)
  347.     local tb = {}; tb.__index = tb
  348.  
  349.     function tb:Select()
  350.         self.toggled = not self.toggled
  351.  
  352.         if (self.handle) then
  353.             self.handle(self)
  354.         end
  355.     end
  356.  
  357.     local mt = {
  358.         __call = function(self, x, y, width, height, handle, text, foreground, background, border)
  359.             local textObj = Text(text, colors.white, background, x, y, width, height)
  360.             local toggleButton = baseClass(x, y, width, height, handle, textObj, foreground, background, border, tb.Select)
  361.  
  362.             setmetatable(toggleButton, tb)
  363.  
  364.             return toggleButton
  365.         end,
  366.  
  367.         __index = baseClass,
  368.     }
  369.  
  370.     setmetatable(tb, mt)
  371.  
  372.     return tb
  373. end) (Button)
  374.  
  375. ButtonGroup = (function(baseClass)
  376.     local g = {}
  377.  
  378.     function g:IsSelected(x, y)
  379.         for name, button in pairs(self.buttons) do
  380.             if (button:IsSelected(x, y)) then
  381.                 button:Select()
  382.             end
  383.         end
  384.     end
  385.  
  386.     function g:AddButton(name, text)
  387.         local count = self.count
  388.  
  389.         local width, height
  390.         if (self.display) then
  391.             width, height = self.display.getSize()
  392.         else
  393.             width, height = term.getSize()
  394.         end
  395.  
  396.         self.maxRows = self.maxRows or math.floor(height / (self.height + self.yGap))
  397.  
  398.         local column = math.floor(count / self.maxRows)
  399.         local row    = math.floor(count - (column * self.maxRows))
  400.  
  401.         local rect = {
  402.             x = 2 + ((self.width + self.xGap) * column),
  403.             y = 2 + ((self.height + self.yGap) * row),
  404.             width = self.width,
  405.             height = self.height,
  406.         }
  407.  
  408.         self.buttons[name] = self.type(rect.x, rect.y, rect.width, rect.height, self.handle, text, self.foreground, self.background)
  409.         self.count = count + 1
  410.     end
  411.  
  412.     function g:AddButtons(tbl)
  413.         for _, name in pairs(tbl) do
  414.             self:AddButton(name, Text(name))
  415.         end
  416.     end
  417.  
  418.     function g:RemoveButton(name)
  419.         if (self.buttons[name]) then
  420.             self.buttons[name] = nil
  421.             self.count = self.count - 1
  422.         end
  423.     end
  424.  
  425.     function g:Clear()
  426.         self.buttons = {}
  427.         self.count = 0
  428.     end
  429.  
  430.     function g:Draw()
  431.         for name, button in pairs(self.buttons) do
  432.             button:Draw(self.display)
  433.         end
  434.     end
  435.  
  436.     local mt = {
  437.         __call = function(self, name, type, handle, width, height, xGap, yGap, foreground, background)
  438.             local group = {
  439.                 name = name,
  440.                 type = type,
  441.                 width = width,
  442.                 handle = handle,
  443.                 height = height,
  444.                 xGap = xGap,
  445.                 yGap = yGap,
  446.                 foreground = foreground,
  447.                 background = background,
  448.                 buttons = {},
  449.                 count = 0,
  450.                 enabled = true,
  451.             }
  452.  
  453.             setmetatable(group, g)
  454.  
  455.             return group
  456.         end,
  457.  
  458.         __index = baseClass,
  459.     }
  460.  
  461.     g.__index = g
  462.  
  463.     setmetatable(g, mt)
  464.  
  465.     return g
  466. end) (Renderable)
  467.  
  468. hpb = HorizontalProgressBar;
  469. vpb = VerticalProgressBar;
  470. pb = PushButton;
  471. tb = ToggleButton;
  472.  
  473. Manager = (function(...)
  474.     local m = {objects = {}, count = 0 }
  475.  
  476.     for _, object in ipairs(arg) do
  477.         assert(type(object) == 'table', 'Attempted to add invalid object to Manager')
  478.  
  479.         m.objects[#m.objects + 1] = object
  480.     end
  481.  
  482.     function m.Add(object)
  483.         m.objects[#m.objects + 1] = object
  484.     end
  485.  
  486.     function m.SafeRun()
  487.         while (true) do
  488.             for _, obj in pairs(m.objects) do
  489.                 if (obj.Run) then
  490.                     result, message = pcall(obj.Run, obj)
  491.  
  492.                     if (not result) then
  493.                         term.redirect(term.native())
  494.                         print(message)
  495.                     end
  496.                 end
  497.             end
  498.  
  499.             local event = {os.pullEvent()}
  500.  
  501.             for _, obj in pairs(m.objects) do
  502.                 if (obj.HandleEvent) then
  503.                     obj:HandleEvent(unpack(event))
  504.                 end
  505.             end
  506.         end
  507.     end
  508.  
  509.     function m.Run()
  510.         local result, message = pcall(m.SafeRun)
  511.  
  512.         if (not result) then
  513.             print(message)
  514.         end
  515.     end
  516.  
  517.     return m
  518. end)
  519.  
  520. -- Parameters:
  521. -- side: which side to grab the display from
  522. Interface = (function()
  523.     local ui = {collection = {}}
  524.  
  525.     function ui:Enable(name)
  526.         assert(type(self) == 'table', 'No reference to instance (self)')
  527.  
  528.         if (self.displayObjects[name]) then
  529.             self.displayObjects[name].enabled = true
  530.         end
  531.     end
  532.  
  533.     function ui:Disable(name)
  534.         assert(type(self) == 'table', 'No reference to instance (self)')
  535.  
  536.         if (self.displayObjects[name]) then
  537.             self.displayObjects[name].enabled = false
  538.         end
  539.     end
  540.  
  541.     function ui:Select(x, y)
  542.         assert(type(self) == 'table', 'No reference to instance (self)')
  543.  
  544.         for _, display in pairs(self.displayObjects) do
  545.             if (display.IsSelected and display:IsSelected(x, y)) then
  546.                 display:Select(self)
  547.             end
  548.         end
  549.     end
  550.  
  551.     function ui:SwitchTo()
  552.         assert(type(self) == 'table', 'No reference to instance (self)')
  553.  
  554.         self:Run()
  555.  
  556.         for name, interface in pairs(ui.interfaces) do
  557.             if (self.name ~= name) then
  558.                 os.queueEvent('stop', name)
  559.             end
  560.         end
  561.     end
  562.  
  563.     function ui:Draw()
  564.         assert(type(self) == 'table', 'No reference to instance (self)')
  565.  
  566.         if (self.display) then
  567.             term.redirect(self.display)
  568.         end
  569.  
  570.         term.setBackgroundColor(colors.black)
  571.         term.clear()
  572.  
  573.         for _, display in pairs(self.displayObjects) do
  574.             display:Draw()
  575.         end
  576.  
  577.         if (self.display) then
  578.             term.redirect(term.native())
  579.         end
  580.     end
  581.  
  582.     function ui:Register(name, object)
  583.         assert(type(self) == 'table', 'No reference to instance (self)')
  584.         assert(type(name) == 'string', 'Must specify a name')
  585.         assert(type(object) == 'table', 'No object provided')
  586.  
  587.         self.displayObjects[name] = object
  588.  
  589.         if (not object.display) then
  590.             object.display = self.display
  591.         end
  592.  
  593.         if (object.SetDisplay) then
  594.             object:SetDisplay(self.display)
  595.         end
  596.     end
  597.  
  598.     function ui:HandleEvent(event, command, x, y)
  599.         assert(type(self) == 'table', 'No reference to instance (self)')
  600.  
  601.         if (event == 'monitor_touch' and command == self.side and x and y) then
  602.             self:Select(x, y)
  603.             self.run = true
  604.         elseif (event == 'stop' and command == self.name) then
  605.             self.run = false
  606.         elseif (event == 'timer') then
  607.             for _, object in pairs (self.displayObjects) do
  608.                 if (object.Handle) then
  609.                     object:Handle(command)
  610.                 end
  611.             end
  612.         end
  613.     end
  614.  
  615.     function ui:Run()
  616.         assert(type(self) == 'table', 'No reference to instance (self)')
  617.  
  618.         if (self.run) then
  619.             self:Draw()
  620.         end
  621.     end
  622.  
  623.     ui.__index = ui
  624.  
  625.     local mt = {
  626.         __call = function(self, name, side, ...)
  627.             local disp = peripheral.wrap(side) or term.current()
  628.  
  629.             assert(disp, 'No display object found')
  630.  
  631.             local userInterface = {
  632.                 display = disp,
  633.                 name = name,
  634.                 side = side,
  635.                 run = true,
  636.                 displayObjects = (function ()
  637.                     local d = {}
  638.  
  639.                     if (arg) then
  640.                         for _, object in ipairs(arg) do
  641.                             object.display = disp
  642.  
  643.                             if (object.SetDisplay) then
  644.                                 object:SetDisplay(disp)
  645.                             end
  646.  
  647.                             d[#d + 1] = object
  648.                         end
  649.                     end
  650.  
  651.                     return d
  652.                 end) (),
  653.             }
  654.  
  655.             setmetatable(userInterface, ui)
  656.  
  657.             ui.collection[name] = userInterface
  658.  
  659.             return userInterface
  660.         end
  661.     }
  662.  
  663.     setmetatable(ui, mt)
  664.  
  665.     return ui
  666. end) ()
  667.  
  668. Server = (function(...)
  669.     local s = {}; s.__index = s
  670.  
  671.     function s:HandleEvent (event, modemSide, senderChannel, replyChannel, message, senderDistance)
  672.         assert(type(self) == 'table', 'No reference to instance (self)')
  673.  
  674.         if (event == 'modem_message') then
  675.             if (senderChannel == self.channel and replyChannel and message) then
  676.                 self.handle(message, replyChannel)
  677.             end
  678.         end
  679.     end
  680.  
  681.     function s:Send(channel, message)
  682.         assert (type(self) == 'table', 'No reference to instance (self)')
  683.  
  684.         if (self.modem) then
  685.             self.modem.transmit(channel, self.channel, message)
  686.         end
  687.     end
  688.  
  689.     function s:SetHandle(handle)
  690.         self.handle = handle
  691.     end
  692.  
  693.     local mt = {
  694.         __call = function(self, channel, handle)
  695.             local inst = {
  696.                 channel = channel,
  697.                 handle = handle,
  698.             }
  699.  
  700.             inst.modem = peripheral.find("modem")
  701.  
  702.             assert(inst.modem, "Could not find modem")
  703.  
  704.             inst.modem.open(channel)
  705.  
  706.             setmetatable(inst, s)
  707.  
  708.             return inst
  709.         end,
  710.     }
  711.  
  712.     setmetatable(s, mt)
  713.  
  714.     return s
  715. end) ()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement