Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- Class Hierarchy
- -- - Renderable
- -- - ProgressBar
- -- - VerticalProgressBar
- -- - HorizontalProgressBar
- -- - Button
- -- - PushButton
- -- - ToggleButton
- -- Renderable
- -- Variables:
- -- x, y, width, height, foreground, background, border
- -- Functions:
- -- DrawBorder()
- -- Update()
- -- IsSelected()
- -- SetHandle()
- local Renderable = (function()
- local r = {}; r.__index = r
- function r:Update()
- if (self.Draw) then
- self:Draw()
- end
- end
- function r:DrawBorder()
- local p1, p2, p3, p4 = self.p1, self.p2, self.p3, self.p4
- if (self.border) then
- paintutils.drawLine(p1.x, p1.y, p2.x, p2.y, self.border)
- paintutils.drawLine(p2.x, p2.y, p3.x, p3.y, self.border)
- paintutils.drawLine(p3.x, p3.y, p4.x, p4.y, self.border)
- paintutils.drawLine(p4.x, p4.y, p1.x, p1.y, self.border)
- end
- end
- function r:SetHandle(handle)
- self.handle = handle
- end
- function r:IsSelected(x, y)
- local xMin, xMax = self.x, self.x + self.width
- local yMin, yMax = self.y, self.y + self.height
- local xValid = x >= xMin and x <= xMax
- local yValid = y >= yMin and y <= yMax
- return xValid and yValid
- end
- local mt = {
- __call = function(self, x, y, width, height, foreground, background, border, funcSelect)
- assert(type(x) == 'number', 'No coordinate for x provided')
- assert(type(y) == 'number', 'No coordinate for y provided')
- local renderable = {
- x = x,
- y = y,
- width = width,
- height = height,
- foreground = foreground,
- background = background,
- border = border,
- enabled = true,
- p1 = {x = x, y = y},
- p2 = {x = x + width, y = y},
- p3 = {x = x + width, y = y + height},
- p4 = {x = x, y = y + height},
- Select = funcSelect or function() print("No function bound to select") end,
- }
- setmetatable(renderable, r)
- return renderable
- end
- }
- setmetatable(r, mt)
- return r
- end) ()
- -- ProgressBar
- -- Variables:
- -- Base: Renderable
- -- New: progress
- local ProgressBar = (function(baseClass)
- local pb = {}; pb.__index = pb
- local mt = {
- __call = function(self, x, y, width, height, foreground, background, border, funcSelect)
- local bar = baseClass(x, y, width, height, foreground, background, border, funcSelect)
- bar.progress = 0
- setmetatable(bar, pb)
- return bar
- end,
- __index = baseClass,
- }
- setmetatable(pb, mt)
- return pb
- end) (Renderable)
- -- Button
- -- Variables:
- -- Base: Renderable
- -- New: handle, text
- -- Functions:
- -- DrawFill,
- -- Draw,
- local Button = (function(baseClass)
- local b = {}; b.__index = b
- -- Description: Draws the inner part of the button
- -- Returns: nil
- function b:DrawFill()
- local fillColour = (self.toggled == true and self.foreground or self.background)
- for x = self.x, self.x + self.width - 1 do
- for y = self.y, self.y + self.height - 1 do
- paintutils.drawPixel(x, y, fillColour)
- end
- end
- end
- -- Description: Draws the button
- -- Returns: nil
- function b:Draw()
- self:DrawFill()
- self:DrawBorder()
- -- Set background for text
- self.text.background = self.toggled and self.foreground or self.background
- -- Draw text on button
- self.text:Draw()
- end
- local mt = {
- __call = function(self, x, y, width, height, handle, text, foreground, background, border, funcSelect)
- local button = baseClass(x, y, width, height, foreground, background, border, funcSelect)
- button.handle = handle
- button.text = text
- button.toggled = false
- setmetatable(button, b)
- return button
- end,
- __index = baseClass,
- }
- setmetatable(b, mt)
- return b
- end) (Renderable)
- VerticalProgressBar = (function (baseClass)
- local vpb = {}; vpb.__index = vpb
- function vpb:Draw()
- -- Calculate width for background and foreground
- local bHeight = math.abs(self.height * ((self.progress - 100) / 100))
- local fHeight = math.abs(self.height * (self.progress / 100))
- -- Draw background
- for i = self.x, self.x + self.width - 1 do
- for j = self.y, self.y + bHeight - 1 do
- paintutils.drawPixel(i, j, self.background)
- end
- end
- -- Draw foreground
- for i = self.x, self.x + self.width - 1 do
- for j = self.y + bHeight, self.y + bHeight + fHeight - 1 do
- paintutils.drawPixel(i, j, self.foreground)
- end
- end
- self:DrawBorder()
- end
- local mt = {
- __call = function(self, x, y, width, height, foreground, background, border, funcSelect)
- local bar = baseClass(x, y, width, height, foreground, background, border, funcSelect)
- setmetatable(bar, vpb)
- return bar
- end,
- __index = baseClass
- }
- setmetatable(vpb, mt)
- return vpb
- end) (ProgressBar)
- HorizontalProgressBar = (function(baseClass)
- local hpb = {}; hpb.__index = hpb
- function hpb:Draw()
- -- Calculate width for background and foreground
- local bWidth = math.abs(self.width * ((self.progress - 100) / 100))
- local fWidth = math.abs(self.width * (self.progress / 100))
- -- Draw background
- for i = self.x + fWidth, self.x + fWidth + bWidth - 1 do
- for j = self.y, self.y + self.height - 1 do
- paintutils.drawPixel(i, j, self.background)
- end
- end
- -- Draw foreground
- for i = self.x, self.x + fWidth - 1 do
- for j = self.y, self.y + self.height - 1 do
- paintutils.drawPixel(i, j, self.foreground)
- end
- end
- self:DrawBorder()
- end
- local mt = {
- __call = function(self, x, y, width, height, foreground, background, border, funcSelect)
- local bar = baseClass(x, y, width, height, foreground, background, border, funcSelect)
- setmetatable(bar, hpb)
- return bar
- end,
- __index = baseClass
- }
- setmetatable(hpb, mt)
- return hpb
- end) (ProgressBar)
- Text = (function(baseClass)
- local t = {}; t.__index = t
- function t:Centre(w, h)
- if (w and h) then
- return math.floor((w / 2) - (#self.text / 2)), math.floor(h / 2)
- else
- return 0, 0
- end
- end
- function t:Write(x, y, w, h)
- if (term) then
- local modX, modY = self:Centre(w, h)
- if (self.background) then
- term.setBackgroundColor(self.background)
- end
- term.setTextColor(self.foreground)
- term.setCursorPos(x + modX, y + modY)
- term.write(self.text)
- -- Reset
- term.setTextColor(colors.white)
- term.setCursorPos(0, 0)
- end
- end
- function t:Draw()
- self:Write(self.x, self.y, self.width, self.height)
- end
- local mt = {
- __call = function(self, text, foreground, background, x, y, width, height)
- assert(type(text) == 'string', 'No text provided')
- local w = width or #text
- local h = height or 1
- local tInstance = baseClass(x, y, w, h, foreground or colors.white, background or colors.black, nil)
- -- Child class member
- tInstance.text = text
- setmetatable(tInstance, t)
- return tInstance
- end,
- __index = baseClass,
- }
- setmetatable(t, mt)
- return t
- end) (Renderable)
- PushButton = (function(baseClass)
- local pb = {}; pb.__index = pb
- function pb:Select()
- self.toggled = true
- if (self.handle) then
- self.handle(self)
- end
- self.timer = os.startTimer(.3)
- end
- function pb:Handle(timer)
- if (self.timer == timer) then
- self.toggled = false
- end
- end
- local mt = {
- __call = function(self, x, y, width, height, handle, text, foreground, background, border)
- local textObj = Text(text, colors.white, background, x, y, width, height)
- local pushButton = baseClass(x, y, width, height, handle, textObj, foreground, background, border, pb.Select)
- setmetatable(pushButton, pb)
- return pushButton
- end,
- __index = baseClass,
- }
- setmetatable(pb, mt)
- return pb
- end) (Button)
- ToggleButton = (function(baseClass)
- local tb = {}; tb.__index = tb
- function tb:Select()
- self.toggled = not self.toggled
- if (self.handle) then
- self.handle(self)
- end
- end
- local mt = {
- __call = function(self, x, y, width, height, handle, text, foreground, background, border)
- local textObj = Text(text, colors.white, background, x, y, width, height)
- local toggleButton = baseClass(x, y, width, height, handle, textObj, foreground, background, border, tb.Select)
- setmetatable(toggleButton, tb)
- return toggleButton
- end,
- __index = baseClass,
- }
- setmetatable(tb, mt)
- return tb
- end) (Button)
- ButtonGroup = (function(baseClass)
- local g = {}
- function g:IsSelected(x, y)
- for name, button in pairs(self.buttons) do
- if (button:IsSelected(x, y)) then
- button:Select()
- end
- end
- end
- function g:AddButton(name, text)
- local count = self.count
- local width, height
- if (self.display) then
- width, height = self.display.getSize()
- else
- width, height = term.getSize()
- end
- self.maxRows = self.maxRows or math.floor(height / (self.height + self.yGap))
- local column = math.floor(count / self.maxRows)
- local row = math.floor(count - (column * self.maxRows))
- local rect = {
- x = 2 + ((self.width + self.xGap) * column),
- y = 2 + ((self.height + self.yGap) * row),
- width = self.width,
- height = self.height,
- }
- self.buttons[name] = self.type(rect.x, rect.y, rect.width, rect.height, self.handle, text, self.foreground, self.background)
- self.count = count + 1
- end
- function g:AddButtons(tbl)
- for _, name in pairs(tbl) do
- self:AddButton(name, Text(name))
- end
- end
- function g:RemoveButton(name)
- if (self.buttons[name]) then
- self.buttons[name] = nil
- self.count = self.count - 1
- end
- end
- function g:Clear()
- self.buttons = {}
- self.count = 0
- end
- function g:Draw()
- for name, button in pairs(self.buttons) do
- button:Draw(self.display)
- end
- end
- local mt = {
- __call = function(self, name, type, handle, width, height, xGap, yGap, foreground, background)
- local group = {
- name = name,
- type = type,
- width = width,
- handle = handle,
- height = height,
- xGap = xGap,
- yGap = yGap,
- foreground = foreground,
- background = background,
- buttons = {},
- count = 0,
- enabled = true,
- }
- setmetatable(group, g)
- return group
- end,
- __index = baseClass,
- }
- g.__index = g
- setmetatable(g, mt)
- return g
- end) (Renderable)
- hpb = HorizontalProgressBar;
- vpb = VerticalProgressBar;
- pb = PushButton;
- tb = ToggleButton;
- Manager = (function(...)
- local m = {objects = {}, count = 0 }
- for _, object in ipairs(arg) do
- assert(type(object) == 'table', 'Attempted to add invalid object to Manager')
- m.objects[#m.objects + 1] = object
- end
- function m.Add(object)
- m.objects[#m.objects + 1] = object
- end
- function m.SafeRun()
- while (true) do
- for _, obj in pairs(m.objects) do
- if (obj.Run) then
- result, message = pcall(obj.Run, obj)
- if (not result) then
- term.redirect(term.native())
- print(message)
- end
- end
- end
- local event = {os.pullEvent()}
- for _, obj in pairs(m.objects) do
- if (obj.HandleEvent) then
- obj:HandleEvent(unpack(event))
- end
- end
- end
- end
- function m.Run()
- local result, message = pcall(m.SafeRun)
- if (not result) then
- print(message)
- end
- end
- return m
- end)
- -- Parameters:
- -- side: which side to grab the display from
- Interface = (function()
- local ui = {collection = {}}
- function ui:Enable(name)
- assert(type(self) == 'table', 'No reference to instance (self)')
- if (self.displayObjects[name]) then
- self.displayObjects[name].enabled = true
- end
- end
- function ui:Disable(name)
- assert(type(self) == 'table', 'No reference to instance (self)')
- if (self.displayObjects[name]) then
- self.displayObjects[name].enabled = false
- end
- end
- function ui:Select(x, y)
- assert(type(self) == 'table', 'No reference to instance (self)')
- for _, display in pairs(self.displayObjects) do
- if (display.IsSelected and display:IsSelected(x, y)) then
- display:Select(self)
- end
- end
- end
- function ui:SwitchTo()
- assert(type(self) == 'table', 'No reference to instance (self)')
- self:Run()
- for name, interface in pairs(ui.interfaces) do
- if (self.name ~= name) then
- os.queueEvent('stop', name)
- end
- end
- end
- function ui:Draw()
- assert(type(self) == 'table', 'No reference to instance (self)')
- if (self.display) then
- term.redirect(self.display)
- end
- term.setBackgroundColor(colors.black)
- term.clear()
- for _, display in pairs(self.displayObjects) do
- display:Draw()
- end
- if (self.display) then
- term.redirect(term.native())
- end
- end
- function ui:Register(name, object)
- assert(type(self) == 'table', 'No reference to instance (self)')
- assert(type(name) == 'string', 'Must specify a name')
- assert(type(object) == 'table', 'No object provided')
- self.displayObjects[name] = object
- if (not object.display) then
- object.display = self.display
- end
- if (object.SetDisplay) then
- object:SetDisplay(self.display)
- end
- end
- function ui:HandleEvent(event, command, x, y)
- assert(type(self) == 'table', 'No reference to instance (self)')
- if (event == 'monitor_touch' and command == self.side and x and y) then
- self:Select(x, y)
- self.run = true
- elseif (event == 'stop' and command == self.name) then
- self.run = false
- elseif (event == 'timer') then
- for _, object in pairs (self.displayObjects) do
- if (object.Handle) then
- object:Handle(command)
- end
- end
- end
- end
- function ui:Run()
- assert(type(self) == 'table', 'No reference to instance (self)')
- if (self.run) then
- self:Draw()
- end
- end
- ui.__index = ui
- local mt = {
- __call = function(self, name, side, ...)
- local disp = peripheral.wrap(side) or term.current()
- assert(disp, 'No display object found')
- local userInterface = {
- display = disp,
- name = name,
- side = side,
- run = true,
- displayObjects = (function ()
- local d = {}
- if (arg) then
- for _, object in ipairs(arg) do
- object.display = disp
- if (object.SetDisplay) then
- object:SetDisplay(disp)
- end
- d[#d + 1] = object
- end
- end
- return d
- end) (),
- }
- setmetatable(userInterface, ui)
- ui.collection[name] = userInterface
- return userInterface
- end
- }
- setmetatable(ui, mt)
- return ui
- end) ()
- Server = (function(...)
- local s = {}; s.__index = s
- function s:HandleEvent (event, modemSide, senderChannel, replyChannel, message, senderDistance)
- assert(type(self) == 'table', 'No reference to instance (self)')
- if (event == 'modem_message') then
- if (senderChannel == self.channel and replyChannel and message) then
- self.handle(message, replyChannel)
- end
- end
- end
- function s:Send(channel, message)
- assert (type(self) == 'table', 'No reference to instance (self)')
- if (self.modem) then
- self.modem.transmit(channel, self.channel, message)
- end
- end
- function s:SetHandle(handle)
- self.handle = handle
- end
- local mt = {
- __call = function(self, channel, handle)
- local inst = {
- channel = channel,
- handle = handle,
- }
- inst.modem = peripheral.find("modem")
- assert(inst.modem, "Could not find modem")
- inst.modem.open(channel)
- setmetatable(inst, s)
- return inst
- end,
- }
- setmetatable(s, mt)
- return s
- end) ()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement