Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local gpu=require("component").gpu
- local isPrimary=require("component").isPrimary
- local event=require("event")
- local len=require("unicode").len
- local sub=require("unicode").sub
- local uchar=require("unicode").char
- local term=require("term")
- local pushSignal=require("computer").pushSignal
- local kbd = require("component").keyboard
- local wrap = require("text").wrap
- local padRight=require("text").padRight
- local isControl= require("keyboard").isControl
- local forms={}
- local mouseEv={touch=true, scroll=true, drag=true, drop=true}
- local activeForm
- local TComponent={left=1,top=1, color=0, fontColor=0xffffff, border=0, visible=true, tag=0, type=function() return "unknown" end}
- TComponent.__index=TComponent
- function TComponent:paint() end
- function TComponent:isVisible()
- if not self.visible then return false end
- if self.parent then return self.parent:isVisible()
- else return self==activeForm
- end
- end
- function TComponent:draw()
- if self.parent then self.X=self.parent.X+self.left-1 self.Y=self.parent.Y+self.top-1
- else self.X=self.left self.Y=self.top end
- gpu.setBackground(self.color)
- gpu.setForeground(self.fontColor)
- local brd=nil
- if self.border==1 then brd={"-","-","¬","L","¦","-"}
- elseif self.border==2 then brd={"г","=","¬","L","¦","-"}
- end
- if brd then
- gpu.set(self.X,self.Y, brd[1]..string.rep(brd[2],self.W-2)..brd[3])
- for i=self.Y+1,self.Y+self.H-2 do
- gpu.set(self.X,i, brd[5]..string.rep(" ",self.W-2)..brd[5])
- end
- gpu.set(self.X,self.Y+self.H-1, brd[4]..string.rep(brd[2],self.W-2)..brd[6])
- else gpu.fill(self.X,self.Y,self.W,self.H," ") end
- self:paint()
- if self.elements then
- for i=1,#self.elements do
- if self.elements[i].visible then self.elements[i]:draw() end
- end
- end
- end
- function TComponent:redraw() if self:isVisible() then self:draw() end end
- function TComponent:makeChild(el)
- if not self.elements then self.elements={} end
- el.parent=self
- table.insert(self.elements,el)
- end
- function TComponent:mouseEv(ev,x,y,btn,user)
- if self.elements then
- for i=#self.elements,1,-1 do
- local e=self.elements[i]
- if e.visible and x>=e.X and x<e.X+e.W and y>=e.Y and y<e.Y+e.H then
- e:mouseEv(ev,x,y,btn,user)
- return
- end
- end
- end
- if self[ev] then self[ev](self, x-self.X+1,y-self.Y+1,btn,user) end
- end
- function TComponent:hide()
- if self.visible then
- self.visible=false
- self.parent:draw()
- end
- end
- function TComponent:show()
- if not self.visible then
- self.visible=true
- self.parent:draw()
- end
- end
- function TComponent:destruct()
- if self.parent then
- for i=1,#self.parent.elements do
- if self.parent.elements[i]==self then table.remove(self.parent.elements,i) break end
- end
- end
- end
- ------------------Form------------------
- local TForm=setmetatable({type=function() return "Form" end},TComponent)
- TForm.__index=TForm
- function TForm:isActive() return self==activeForm end
- function TForm:setActive()
- if activeForm~=self then
- activeForm=self
- self:draw()
- end
- end
- function forms.addForm()
- local obj={}
- TForm.W, TForm.H=gpu.getResolution()
- return setmetatable(obj,TForm)
- end
- ------------------Button----------------
- local TButton=setmetatable({W=10, H=1, color=0x606060, type=function() return "Button" end},TComponent)
- TButton.__index=TButton
- function TButton:touch(x, y, btn, user)
- if self.onClick and btn==0 then self:onClick(user) end
- end
- function TButton:paint()
- gpu.set(self.X+(self.W-len(self.caption))/2,self.Y+(self.H-1)/2, self.caption)
- end
- function TComponent:addButton(left, top, caption, onClick)
- local obj={left=left, top=top, caption=caption or "Button", onClick=onClick}
- self:makeChild(obj)
- return setmetatable(obj,TButton)
- end
- ------------------Label-----------------
- local TLabel=setmetatable({H=1, centered=false, autoSize=true, type=function() return "Label" end} ,TComponent)
- TLabel.__index=TLabel
- function TLabel:paint()
- local line
- local value=tostring(self.caption)
- if self.autoSize then
- self.W,self.H=0,0
- for line in value:gmatch("([^\n]+)") do
- self.H=self.H+1
- if len(line)>self.W then self.W=len(line) end
- end
- if self.W<1 then self.W=1 end
- if self.H<1 then self.H=1 end
- end
- for i=0,self.H-1 do
- if not value then break end
- line, value = wrap(value, self.W, self.W)
- if self.centered then gpu.set(self.X+(self.W-len(line))/2,self.Y+i, line)
- else gpu.set(self.X,self.Y+i, line) end
- end
- end
- function TComponent:addLabel(left, top, caption)
- local obj={left=left, top=top, caption=caption or "Label"}
- obj.W=len(obj.caption)
- self:makeChild(obj)
- return setmetatable(obj,TLabel)
- end
- ------------------Edit------------------
- local TEdit=setmetatable({W=20, H=3, text="", border=1, type=function() return "Edit" end},TComponent)
- TEdit.__index=TEdit
- function TEdit:paint()
- if type(self.text)=="table" then
- for i=1,self.H-2 do gpu.set(self.X+1,self.Y+i,sub(self.text[i] or "",1,self.W-2)) end
- else gpu.set(self.X+1,self.Y+1, sub(self.text,1,self.W-2))
- end
- end
- local function editText(text,left,top,W,H)
- local running=true
- local scrollX, scrollY = 0, 0
- local posX, posY =1, 1
- local writeText
- local function setCursor(nx,ny)
- posX=nx or posX
- posY=ny or posY
- if #text<1 then text[1]="" end
- if posY>#text then posY=#text end
- if posY<1 then posY=1 end
- if posX>len(text[posY])+1 then posX=len(text[posY])+1 end
- if posX<1 then posX=1 end
- local redraw=false
- if posY<=scrollY then scrollY=posY-1 redraw=true end
- if posY>scrollY+H then scrollY=posY-H redraw=true end
- if posX<=scrollX then scrollX=posX-1 redraw=true end
- if posX>scrollX+W then scrollX=posX-W redraw=true end
- if redraw then writeText()
- else term.setCursor(left+posX-scrollX-1, top+posY-scrollY-1) end
- end
- local function writeLine(n)
- gpu.set(left,top+n-scrollY-1,padRight(sub(text[n] or "",scrollX+1,scrollX+W),W))
- end
- function writeText()
- for i=1,H do writeLine(i+scrollY) end
- setCursor()
- end
- local function insert(value)
- if not value or len(value) < 1 then return end
- text[posY]=sub(text[posY],1,posX-1)..value..sub(text[posY],posX)
- writeLine(posY)
- setCursor(posX+len(value))
- end
- local keys={}
- keys[203]=function() -- Left
- if posX>1 then setCursor(posX-1)
- else if posY>1 then posY=posY-1 setCursor(len(text[posY])+1) end
- end
- end
- keys[205]=function() -- Right
- if posX<=len(text[posY]) then setCursor(posX+1)
- else if posY<#text then setCursor(1,posY+1) end
- end
- end
- keys[199]=function() setCursor(1) end -- Home
- keys[207]=function() setCursor(len(text[posY])+1) end -- End
- keys[211]=function() -- Del
- if posX<=len(text[posY]) then
- text[posY]=sub(text[posY],1,posX-1)..sub(text[posY],posX+1)
- writeLine(posY)
- else
- if posY<#text then
- text[posY]=text[posY]..text[posY+1]
- table.remove(text,posY+1)
- writeText()
- end
- end
- end
- keys[14] =function() -- BackSp
- if posX>1 then
- text[posY]=sub(text[posY],1,posX-2)..sub(text[posY],posX)
- writeLine(posY)
- setCursor(posX-1)
- else
- if posY>1 then
- posX,posY,text[posY-1]=len(text[posY-1])+1,posY-1,text[posY-1]..text[posY]
- table.remove(text,posY+1)
- writeText()
- end
- end
- end
- keys[15] =function() insert(" ") end -- Tab
- local function onKeyDown(char, code)
- if keys[code] then keys[code]()
- else if not isControl(char) then insert(uchar(char)) end
- end
- end
- local function onClipboard(value)
- end
- local function onClick(x,y)
- if x>=left and x<left+W and y>=top and y<top+H then
- setCursor(x+scrollX-left+1,y+scrollY-top+1)
- else running=false
- end
- end
- local function onScroll(direction)
- end
- if type(text)=="table" then
- keys[68] =function() running=false end -- F10
- keys[200]=function() setCursor(posX,posY-1) end -- Up
- keys[208]=function() setCursor(posX,posY+1) end -- Down
- keys[28] =function() -- Enter
- local n=len(text[posY]:match("^%s*"))
- table.insert(text,posY+1,string.rep(" ",n)..sub(text[posY],posX))
- text[posY]=sub(text[posY],1,posX-1)
- posX,posY=n+1,posY+1
- writeText()
- end
- else
- posX=len(text)+1
- text={tostring(text)}
- keys[28] =function() running=false end -- Enter
- end
- term.setCursorBlink(true)
- writeText()
- while running do
- local event, address, arg1, arg2, arg3 = event.pull()
- if type(address) == "string" and isPrimary(address) then
- term.setCursorBlink(false)
- if event == "key_down" then onKeyDown(arg1, arg2)
- elseif event == "clipboard" then onClipboard(arg1)
- elseif event == "touch" or event == "drag" then onClick(arg1, arg2)
- elseif event == "scroll" then onScroll(arg3)
- end
- term.setCursorBlink(true)
- end
- end
- term.setCursorBlink(false)
- return text[1]
- end
- function TEdit:touch(x, y, btn, user)
- if btn==0 then
- gpu.setBackground(self.color)
- gpu.setForeground(self.fontColor)
- if type(self.text)=="table" then editText(self.text,self.X+1,self.Y+1,self.W-2,self.H-2)
- else self.text=editText(self.text,self.X+1,self.Y+1,self.W-2,1) end
- self:draw()
- if self.onEnter then self:onEnter(user) end
- end
- end
- function TComponent:addEdit(left, top, onEnter)
- local obj={left=left, top=top, onEnter=onEnter}
- self:makeChild(obj)
- return setmetatable(obj,TEdit)
- end
- ------------------Frame-----------------
- local TFrame=setmetatable({W=20, H=10, border=1, type=function() return "Frame" end},TComponent)
- TFrame.__index=TFrame
- function TComponent:addFrame(left, top, border)
- local obj={left=left, top=top, border=border}
- self:makeChild(obj)
- return setmetatable(obj,TFrame)
- end
- ------------------List------------------
- local TList=setmetatable({W=20, H=10, selColor=0x0000ff, sfColor=0xffff00,
- type=function() return "List" end},TComponent)
- TList.__index=TList
- function TList:paint()
- gpu.setForeground(self.sfColor)
- gpu.setBackground(self.selColor)
- local items=self.items
- local y=self.top-1
- local x=self.left
- for i=1,#items do
- gpu.set(x,y+i,items[i].text)
- end
- end
- function TList:clear()
- self.items={}
- self:redraw()
- end
- function TList:insert(pos,line,item)
- end
- function TList:sort(comp)
- end
- function TList:touch(x, y, btn, user)
- self:hide()
- self.items[y].func()
- end
- function TList:scroll(x, y, sh, user)
- end
- function TComponent:addList(left, top, onChange)
- local obj={left=left, top=top, lines={}, items={}, onChange=onChange}
- self:makeChild(obj)
- return setmetatable(obj,TList)
- end
- ----------------------------------------
- local work,Fc,Bc
- function forms.run(form)
- work, Fc, Bc = true, gpu.getForeground(), gpu.getBackground()
- activeForm=form
- activeForm:draw()
- while work do
- local ev,adr,x,y,btn,user=event.pull()
- if mouseEv[ev] and adr==gpu.getScreen() then activeForm:mouseEv(ev,x,y,btn,user) end
- end
- end
- function forms.stop()
- work=false
- gpu.setForeground(Fc)
- gpu.setBackground(Bc)
- end
- function forms.pull(...)
- local ev
- while true do
- ev={event.pull(...)}
- if mouseEv[ev[1]] and ev[2]==gpu.getScreen() then activeForm:mouseEv(ev[1],ev[3],ev[4],ev[5],ev[6])
- else return unpack(ev)
- end
- end
- end
- return forms
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement