Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local component = require("component")
- local computer = require("computer")
- local event = require("event")
- local serialization = require("serialization")
- local unicode = require("unicode")
- local keyboard = require("keyboard")
- local gpu = component.gpu
- local w,h = gpu.maxResolution()
- local GUI = {}
- GUIElements = {} --need to set local
- local inFocus = nil
- GUI.gpu = gpu
- GUI.background = 0x000000
- function del(arr,index)
- arr[index] = arr[#arr]
- arr[#arr] = nil
- end
- --TESTPRINT
- function pr(str)
- GUI.gpu.set(1,24,tostring(str).." ")
- end
- --округление числа
- function math.round(num, idp)
- local mult = 10^(idp or 0)
- return math.floor(num * mult + 0.5) / mult
- end
- function inRect(x,y,rect)
- if x >= rect.left and x<= rect.left+rect.width-1 then
- if y >= rect.top and y<= rect.top+rect.height-1 then
- return true
- end
- end
- return false
- end
- function getClickedElement(x,y)
- for k = #GUIElements,1,-1 do
- local l,t = getAbsPos(GUIElements[k])
- if inRect(x,y,{left=l,top=t,width=GUIElements[k].width,height=GUIElements[k].height}) then
- return GUIElements[k]
- end
- end
- end
- function getAbsPos(elem)
- local t = elem.top
- local l = elem.left
- while elem.owner do
- t = t + elem.owner.top-1
- l = l + elem.owner.left-1
- elem = elem.owner
- end
- return l,t
- end
- function GUI.init()
- event.listen("touch", onTouch)
- event.listen("drag", onDrag)
- event.listen("drop", onDrop)
- event.listen("scroll", onScroll)
- gpu.setResolution(w,h)
- end
- function GUI.Draw()
- GUI.gpu.setBackground(GUI.background)
- GUI.gpu.fill(1,1,w,h," ")
- for k = 1,#GUIElements do
- if GUIElements[k] then
- if GUIElements[k].Draw and not GUIElements[k].owner then
- GUIElements[k].Draw()
- end
- end
- end
- end
- function GUI.Destroy()
- for k = 1,#GUIElements do
- if GUIElements[k].Destroy then
- GUIElements[k].Destroy()
- end
- end
- cursor.stop()
- end
- cursor = {}
- do --InitCursor
- cursor.color = 0xffffee
- cursor.x = 1
- cursor.y = 1
- cursor.length = 10
- cursor.buffer = ""
- cursor.isBlinking = false
- cursor.Blink = {state=false,lastChar = "",caretChar=unicode.char(0x2588),timer=nil}
- function cursor.toggle()
- if cursor.Blink.state then
- GUI.gpu.set(cursor.cx,cursor.cy,cursor.Blink.lastChar)
- else
- cursor.Blink.lastChar = GUI.gpu.get(cursor.cx,cursor.cy)
- GUI.gpu.set(cursor.cx,cursor.cy,cursor.Blink.caretChar)
- end
- cursor.Blink.state = not cursor.Blink.state
- end
- function cursor.SetBlink(flag)
- if flag then
- if not cursor.Blink.timer then
- cursor.Blink.timer = event.timer(0.5,cursor.toggle,math.huge)
- cursor.isBlinking = true
- end
- else
- if cursor.Blink.timer then
- event.cancel(cursor.Blink.timer)
- if cursor.Blink.state then cursor.toggle() end
- cursor.Blink.lastChar = ""
- cursor.Blink.timer = nil
- cursor.isBlinking = false
- end
- end
- end
- function cursor.init(settings)
- cursor.x = settings.x or cursor.x
- cursor.y = settings.y or cursor.y
- cursor.length = settings.length or cursor.length
- cursor.buffer = settings.buffer or cursor.buffer
- cursor.cx = cursor.x + string.len(cursor.buffer)
- cursor.cy = cursor.y
- event.listen("key_down",cursor.OnKeyDown)
- cursor.SetBlink(true)
- end
- function cursor.stop()
- event.ignore("key_down",cursor.OnKeyDown)
- cursor.lastValue = cursor.buffer
- cursor.buffer = ""
- cursor.SetBlink(false)
- return cursor.lastValue
- end
- function cursor.add(char)
- if string.len(cursor.buffer)<cursor.length-1 then
- cursor.buffer = cursor.buffer .. char
- GUI.gpu.set(cursor.cx,cursor.cy,char)
- cursor.cx = cursor.cx + 1
- end
- end
- function cursor.delete()
- if string.len(cursor.buffer)>0 then
- cursor.buffer = string.sub(cursor.buffer,1,string.len(cursor.buffer)-1)
- GUI.gpu.set(cursor.cx-1,cursor.cy," ")
- cursor.cx = cursor.cx - 1
- end
- end
- function cursor.OnKeyDown(signal,addres,char,code)
- cursor.SetBlink(false)
- if code == keyboard.keys.back then
- cursor.delete()
- elseif code == keyboard.keys.enter then
- elseif not keyboard.isControl(char) then
- cursor.add(unicode.char(char))
- --GUI.gpu.set(1,1,cursor.buffer .. " ")
- end
- cursor.toggle()
- cursor.SetBlink(true)
- end
- --function cursor.
- end
- -- classes
- function GUI.Button (args)
- local button = {}
- local settings = args or {}
- button.width = settings.width or 6
- button.height = settings.height or 1
- button.top = settings.top or 1
- button.left = settings.left or 1
- button.text = settings.text or "Button"
- button.textColor = settings.textColor or 0x000000
- button.backgroundColor = settings.backgroundColor or 0x880000
- button.unableColor = settings.unableColor or 0x404020
- button.enable = settings.enable or true
- button.rect = {top = button.top,left = button.left, width = button.width, height = button.height}
- button.type = "BUTTON"
- button.OnClick = nil
- button.index = #GUIElements+1
- GUIElements[#GUIElements+1] = button
- function button.Draw(parameters)
- local left,top = getAbsPos(button)
- local params = parameters or {}
- local bgColor = params.backgroundColor or button.backgroundColor
- if button.enable then
- GUI.gpu.setBackground(bgColor)
- else
- GUI.gpu.setBackground(button.unableColor)
- end
- GUI.gpu.setForeground(button.textColor)
- GUI.gpu.fill(left,top,button.width,button.height," ")
- if string.len(button.text) < button.width then
- local indent = math.floor((button.width - string.len(button.text))/2)
- GUI.gpu.set(left+indent,top,button.text)
- else
- GUI.gpu.set(left,top,string.sub(button.text,1,button.width))
- end
- end
- function button.Destroy()
- del(GUIElements,button.index)
- if button.timer then
- event.cancel(button.timer)
- end
- end
- function button.touchController (...)
- if button.enable then
- button.Draw({backgroundColor=0x008800})
- button.timer = event.timer(0.25,function() button.Draw() button.timer = nil end)
- if button.OnClick then
- button.OnClick(...)
- end
- end
- end
- return button
- end
- function GUI.Label (args)
- local label = {}
- local settings = args or {}
- label.width = settings.width or 6
- label.height = settings.height or 1
- label.top = settings.top or 1
- label.left = settings.left or 1
- label.text = settings.text or "label"
- label.textColor = settings.textColor or 0x000000
- label.backgroundColor = settings.backgroundColor or 0x880000
- label.rect = {top = label.top,left = label.left, width = label.width, height = label.height}
- label.type = "LABEL"
- label.OnClick = nil
- label.index = #GUIElements+1
- GUIElements[#GUIElements+1] = label
- function label.Draw()
- local left,top = getAbsPos(button)
- GUI.gpu.setBackground(label.backgroundColor)
- GUI.gpu.setForeground(label.textColor)
- GUI.gpu.fill(left,top,label.width,label.height," ")
- if string.len(label.text) > label.width then
- GUI.gpu.set(left,top,string.sub(label.text,1,label.width))
- else
- GUI.gpu.set(left,top,label.text)
- end
- end
- function label.Destroy()
- del(GUIElements,label.index)
- end
- function label.touchController (...)
- if label.OnClick then
- label.OnClick(...)
- end
- end
- return label
- end
- function GUI.Panel (args)
- local FrameChars
- local FrameCharsD = {lt = unicode.char(9556),rt = unicode.char(9559),lb = unicode.char(9562),rb = unicode.char(9565), hor = unicode.char(9552), ver = unicode.char(9553)}
- local FrameCharsS = {lt = unicode.char(9556),rt = unicode.char(9559),lb = unicode.char(9562),rb = unicode.char(9565), hor = unicode.char(9552), ver = unicode.char(9553)}
- local panel = {}
- local settings = args or {}
- panel.width = settings.width or 6
- panel.height = settings.height or 1
- panel.top = settings.top or 1
- panel.left = settings.left or 1
- panel.frame = settings.frame or "D"
- panel.caption = settings.caption or ""
- if panel.frame == "D" then
- FrameChars = FrameCharsD
- elseif panel.frame == "S" then
- FrameChars = FrameCharsS
- end
- panel.frameColor = settings.textColor or 0xffffff
- panel.backgroundColor = settings.backgroundColor or 0x0000ff
- panel.items = {}
- local elements = {}
- panel.rect = {top = panel.top,left = panel.left, width = panel.width, height = panel.height}
- panel.type = "PANEL"
- panel.OnClick = nil
- panel.index = #GUIElements+1
- GUIElements[#GUIElements+1] = panel
- function panel.items.add(name,value)
- if panel.items.has(name) then
- error("List already have that element")
- else
- elements[name] = value
- value.owner = panel
- end
- end
- function panel.items.remove(name)
- if panel.items.has(name) then
- elements[name].Destroy()
- elements[name] = nil
- end
- end
- function panel.items.has(name)
- if elements[name] then
- return true
- else
- return false
- end
- end
- function panel.Draw()
- local left,top = getAbsPos(panel)
- GUI.gpu.setBackground(panel.backgroundColor)
- GUI.gpu.setForeground(panel.frameColor)
- GUI.gpu.fill(left,top,panel.width,panel.height," ")
- if panel.frame then
- GUI.gpu.set(left,top,FrameChars.lt)
- for k = left+1,left+panel.width-2 do
- GUI.gpu.set(k,top,FrameChars.hor)
- end
- GUI.gpu.set(left+panel.width-1,top,FrameChars.rt)
- for k = top+1,top+panel.height-2 do
- GUI.gpu.set(left,k,FrameChars.ver)
- GUI.gpu.set(left+panel.width-1,k,FrameChars.ver)
- end
- GUI.gpu.set(left,top+panel.height-1,FrameChars.lb)
- for k = left+1,left+panel.width-2 do
- GUI.gpu.set(k,top+panel.height-1,FrameChars.hor)
- end
- GUI.gpu.set(left+panel.width-1,top+panel.height-1,FrameChars.rb)
- end
- if string.len(panel.caption) > 0 then
- GUI.gpu.set(left+2,top," " .. panel.caption .. " ")
- end
- for k in pairs(elements) do
- if elements[k].Draw then
- elements[k].Draw()
- end
- end
- end
- function panel.Destroy()
- del(GUIElements,panel.index)
- for k in pairs(elements) do
- panel.items.remove(k)
- end
- end
- function panel.touchController (...)
- if panel.OnClick then
- panel.OnClick(...)
- end
- end
- return panel
- end
- function GUI.Edit (args)
- local edit = {}
- local settings = args or {}
- edit.width = settings.width or 6
- edit.height = settings.height or 1
- edit.top = settings.top or 1
- edit.left = settings.left or 1
- edit.text = settings.text or "edit"
- edit.textColor = settings.textColor or 0x000000
- edit.backgroundColor = settings.backgroundColor or 0x880000
- edit.rect = {top = edit.top,left = edit.left, width = edit.width, height = edit.height}
- edit.type = "EDIT"
- edit.OnClick = nil
- edit.index = #GUIElements+1
- GUIElements[#GUIElements+1] = edit
- function edit.Draw()
- local left,top = getAbsPos(edit)
- GUI.gpu.setBackground(edit.backgroundColor)
- GUI.gpu.setForeground(edit.textColor)
- GUI.gpu.fill(left,top,edit.width,edit.height," ")
- if string.len(edit.text) > edit.width then
- GUI.gpu.set(left,top,string.sub(edit.text,1,edit.width))
- else
- GUI.gpu.set(left,top,edit.text)
- end
- end
- function edit.OnFocus()
- GUI.gpu.setBackground(edit.backgroundColor)
- GUI.gpu.setForeground(edit.textColor)
- local left,top = getAbsPos(edit)
- cursor.init({x=left,y=top,buffer=edit.text,length=edit.width})
- end
- function edit.UnFocus()
- edit.text = cursor.stop()
- end
- function edit.Destroy()
- del(GUIElements,edit.index)
- end
- function edit.touchController (...)
- if edit.OnClick then
- edit.OnClick(...)
- end
- end
- return edit
- end
- function GUI.Listbox (args)
- local FrameChars = {lt = unicode.char(9556),rt = unicode.char(9559),lb = unicode.char(9562),rb = unicode.char(9565), hor = unicode.char(9552), ver = unicode.char(9553)}
- local ControlChars = {arUp = unicode.char(9650),arDown = unicode.char(9660),caret = unicode.char(9608),caretLine = unicode.char(9617)}
- local listbox = {}
- local settings = args or {}
- listbox.width = settings.width or 6
- listbox.height = settings.height or 1
- listbox.top = settings.top or 1
- listbox.left = settings.left or 1
- listbox.frame = settings.frame or true
- listbox.frameColor = settings.frameColor or 0xffffff
- listbox.textColor = settings.textColor or 0xffffff
- listbox.selectColor = settings.selectColor or 0xff0000
- listbox.selectTextColor = settings.selectTextColor or 0xffffff
- listbox.backgroundColor = settings.backgroundColor or 0x0000ff
- listbox.items = {}
- listbox.rect = {top = listbox.top,left = listbox.left, width = listbox.width, height = listbox.height}
- listbox.type = "LISTBOX"
- listbox.topIndex = 1
- listbox.selected = 0
- listbox.items= {}
- listbox.Scroll = {position = 1}
- listbox.index = #GUIElements+1
- GUIElements[#GUIElements+1] = listbox
- function listbox.items.add(text)
- listbox.items[#listbox.items+1] = {text = text,OnSelect = nil}
- end
- function listbox.items.count()
- return #listbox.items
- end
- function listbox.items.remove(index)
- for k = index,#listbox.items do
- listbox.items[k] = listbox.items[k+1]
- end
- if listbox.selected > #listbox.items then
- listbox.selected = #listbox.items
- end
- end
- function listbox.Draw()
- local left,top = getAbsPos(listbox)
- GUI.gpu.setBackground(listbox.backgroundColor)
- GUI.gpu.setForeground(listbox.frameColor)
- GUI.gpu.fill(left,top,listbox.width,listbox.height," ")
- if listbox.frame then
- GUI.gpu.set(left,top,FrameChars.lt)
- for k = left+1,left+listbox.width-2 do
- GUI.gpu.set(k,top,FrameChars.hor)
- end
- GUI.gpu.set(left+listbox.width-1,top,FrameChars.rt)
- for k = top+1,top+listbox.height-2 do
- GUI.gpu.set(left,k,FrameChars.ver)
- end
- listbox.DrawControl()
- GUI.gpu.set(left,top+listbox.height-1,FrameChars.lb)
- for k = left+1,left+listbox.width-2 do
- GUI.gpu.set(k,top+listbox.height-1,FrameChars.hor)
- end
- GUI.gpu.set(left+listbox.width-1,top+listbox.height-1,FrameChars.rb)
- local count
- if #listbox.items > listbox.height - 2 then
- count = listbox.height - 2
- else
- count = #listbox.items
- end
- GUI.gpu.setBackground(listbox.backgroundColor)
- GUI.gpu.setForeground(listbox.textColor)
- for k = 1, count do
- if listbox.items[k-1+listbox.topIndex] then
- if string.len(listbox.items[k-1+listbox.topIndex].text) > listbox.width - 2 then
- GUI.gpu.set(left+1,top+k,string.sub(listbox.items[k-1+listbox.topIndex].text,1,listbox.width-2))
- else
- GUI.gpu.set(left+1,top+k,listbox.items[k-1+listbox.topIndex].text)
- end
- end
- end
- listbox.DrawSelect(listbox.selected)
- end
- end
- function listbox.DrawSelect(index)
- local left,top = getAbsPos(listbox)
- if listbox.selected >= listbox.topIndex and listbox.selected <= listbox.topIndex + listbox.height-3 then
- GUI.gpu.setBackground(listbox.backgroundColor)
- GUI.gpu.setForeground(listbox.textColor)
- local top = listbox.selected - listbox.topIndex + 2
- GUI.gpu.fill(left+1,top,listbox.width-2,1," ")
- if string.len(listbox.items[listbox.selected].text) > listbox.width - 2 then
- GUI.gpu.set(left+1,top,string.sub(listbox.items[listbox.selected].text,1,listbox.width-2))
- else
- GUI.gpu.set(left+1,top,listbox.items[listbox.selected].text)
- end
- end
- if index >= listbox.topIndex and index <= listbox.topIndex + listbox.height-3 then
- GUI.gpu.setBackground(listbox.selectColor)
- GUI.gpu.setForeground(listbox.selectTextColor)
- local top = index - listbox.topIndex + 2
- GUI.gpu.fill(left+1,top,listbox.width-2,1," ")
- if string.len(listbox.items[index].text) > listbox.width - 2 then
- GUI.gpu.set(left+1,top,string.sub(listbox.items[index].text,1,listbox.width-2))
- else
- GUI.gpu.set(left+1,top,listbox.items[index].text)
- end
- end
- end
- function listbox.DrawControl()
- local left,top = getAbsPos(listbox)
- GUI.gpu.set(left+listbox.width-1,top+1,ControlChars.arUp)
- for k = top+2,top+listbox.height-3 do
- GUI.gpu.set(left+listbox.width-1,k,ControlChars.caretLine)
- end
- GUI.gpu.set(left+listbox.width-1,top+listbox.height-2,ControlChars.arDown)
- GUI.gpu.set(left+listbox.width-1,top+1 + listbox.Scroll.position,ControlChars.caret)
- end
- function listbox.Destroy()
- del(GUIElements,listbox.index)
- end
- function listbox.touchController (...)
- local args = {...}
- local left,top = getAbsPos(listbox)
- local x = args[3]
- local y = args[4]
- pr(tostring(x) .. " " .. y .. " " .. left .. " " ..top)
- if x == left+ listbox.width-1 and y == top+1 then
- listbox.OnUpControlClick()
- elseif x == left+ listbox.width-1 and y == top+listbox.height-2 then
- listbox.OnDownControlClick()
- elseif x == left + listbox.width-1 and y >= top+2 and y <= top+listbox.height-3 then
- listbox.OnScrollClick(y-(top+1))
- elseif x > left and x<left + listbox.width - 1 and y > top and y <top+listbox.height -1 then
- listbox.OnItemSelect(y-(top+1))
- end
- end
- function listbox.UpdateScrollPos()
- local listHeight = listbox.height -2
- local overCount = #listbox.items - listHeight
- if overCount > 0 then
- local linesInScrollPixel = overCount/listHeight
- listbox.Scroll.position = math.floor((listbox.topIndex-1)/linesInScrollPixel)
- else
- listbox.Scroll.position = 1
- end
- end
- function listbox.OnUpControlClick()
- if listbox.topIndex > 1 then
- listbox.topIndex = listbox.topIndex - 1
- listbox.UpdateScrollPos()
- listbox.Draw()
- end
- end
- function listbox.OnDownControlClick()
- local listHeight = listbox.height -2
- local overCount = #listbox.items - listHeight
- if listbox.topIndex <= overCount then
- listbox.topIndex = listbox.topIndex + 1
- listbox.UpdateScrollPos()
- listbox.Draw()
- end
- end
- function listbox.OnScrollClick(index)
- local listHeight = listbox.height -2
- local overCount = #listbox.items - listHeight
- if overCount > 0 then
- local linesInScrollPixel = overCount/listHeight
- listbox.topIndex = math.round(1+ math.round(linesInScrollPixel*index))
- listbox.Scroll.position = index
- else
- listbox.Scroll.position = 1
- listbox.topIndex = 1
- end
- listbox.Draw()
- end
- function listbox.OnItemSelect(index)
- local selIndex = listbox.topIndex + index
- if selIndex <= #listbox.items then
- listbox.selected = selIndex
- listbox.DrawSelect(selIndex)
- end
- end
- return listbox
- end
- function onTouch(eventName,screenAddress, x, y, button, playerName)
- local elem = getClickedElement(x,y)
- if inFocus then
- if inFocus.UnFocus then
- inFocus.UnFocus()
- inFocus = nil
- end
- end
- if elem then
- if elem.OnFocus then
- elem.OnFocus()
- inFocus = elem
- end
- if elem.touchController then
- elem.touchController(eventName,screenAddress, x, y, button, playerName)
- end
- end
- end
- function onDrag(eventName,screenAddress, x, y, button, playerName)
- --print("drag")
- end
- function onDrop(eventName,screenAddress, x, y, button, playerName)
- --print("drop")
- end
- function onScroll(eventName,screenAddress, x, y, direction, playerName)
- --print("scroll")
- end
- function GUI.Destroy()
- event.ignore("touch", onTouch)
- event.ignore("drag", onDrag)
- event.ignore("drop", onDrop)
- event.ignore("scroll", onScroll)
- end
- return GUI
Add Comment
Please, Sign In to add comment