Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local ui = {}
- ui.elements = {
- line = {
- draw = function(self, x, y)
- local x2, y2 = x, y
- if self.y2 then y2 = self.y2-(self.y-y) end
- if self.x2 then x2 = self.x2-(self.x-x) end
- paintutils.drawLine(x, y, x2, y2)
- end
- },
- button = {
- clickedColor = colors.white, label = "", _onPressed = function(self) end, _onReleased = function(self) end,
- update = function(self)
- end,
- draw = function(self, x, y)
- local color = self.color
- if self.isPressed then color = self.clickedColor end
- term.setBackgroundColor(color)
- term.write(self.label)
- end,
- onClick = function(self)
- self.isPressed = true
- end,
- onMouse_up = function(self)
- self.isPressed = false
- end
- },
- label = {
- x = 1, y = 1, w = 1, h = 1, color = colors.gray, textColor = colors.white, text = "",
- draw = function(self, x, y)
- term.write(self.text)
- end
- },
- checkbox = {
- ticked = false,
- draw = function(self, x, y)
- if ticked then
- term.write("x")
- else
- term.write(" ")
- end
- end,
- onClick = function(self)
- self.ticked = not self.ticked
- end
- },
- panel = {
- },
- box = {},
- textinput = {
- text = "", onFinished = function(self, text) end,
- draw = function(self, x, y)
- paintutils.drawLine(x, y, x+self.w-1, y+self.h-1)
- term.setCursorPos(x, y)
- term.write(self.text)
- end,
- onChar = function(self, char)
- self.text = self.text..char
- end,
- onKey = function(self, key)
- if key == keys.backspace then
- self.text = string.sub(self.text, 1, #self.text-1)
- elseif key == keys.enter then
- self:onFinished(self.text)
- end
- end
- },
- textedit = {
- textColor = colors.white, cursorColor = colors.lightGray, keywordColor = colors.magenta, tablecallColor = colors.red, stringColor = colors.lime, numberColor = colors.orange, commentColor = colors.gray, argumentColor = colors.cyan,
- text = {
- [1] = "",
- [2] = ""
- },
- movement = {
- up = { 0, -1},
- down = { 0, 1},
- left = {-1, 0},
- right = { 1, 0},
- },
- keywords = {
- "and",
- "break",
- "do",
- "else",
- "elseif",
- "end",
- "false",
- "for",
- "function",
- "if",
- "in",
- "local",
- "nil",
- "not",
- "or",
- "repeat",
- "return",
- "then",
- "true",
- "until",
- "while"
- },
- cursorX = 1, cursorY = 1,
- scrollY = 0,
- moveTo = function(self, x, y)
- if not self.text[y] then self.text[y] = "" end
- local x, y = x, y
- if x < 1 and self.cursorY > 1 then return self:moveTo(#self.text[y-1]+1, y-1)
- elseif x < 1 then
- x = 1
- end
- if y < 1 then y = 1 end
- if x > #self.text[y]+1 then x = #self.text[y]+1 end
- if y > #self.text then y = #self.text end
- if y > self.h-self.scrollY then
- self.scrollY = self.scrollY - 1
- elseif y <= -self.scrollY then
- self.scrollY = self.scrollY + 1
- end
- self.cursorX, self.cursorY = x, y
- end,
- move = function(self, x, y)
- self:moveTo(self.cursorX+x, self.cursorY+y)
- end,
- onChar = function(self, char)
- local oldLine = self.text[self.cursorY]
- self.text[self.cursorY] = string.sub(oldLine, 1, self.cursorX-1)..char..string.sub(oldLine, self.cursorX)
- self:move(1, 0)
- self:makeTextChangedCallback()
- end,
- onKey = function(self, key)
- local keyname = keys.getName(key)
- if keyname == "backspace" then
- if self.cursorX == 1 and self.cursorY>1 then
- local textLength = #self.text[self.cursorY-1]
- self.text[self.cursorY-1] = self.text[self.cursorY-1]..self.text[self.cursorY]
- table.remove(self.text, self.cursorY)
- self:moveTo(textLength+1, self.cursorY-1)
- elseif self.cursorX > 1 and self.cursorY > 0 then
- self.text[self.cursorY] = string.sub(self.text[self.cursorY], 1, self.cursorX-2)..string.sub(self.text[self.cursorY], self.cursorX)
- self:move(-1, 0)
- end
- elseif self.movement[keyname] then
- local toMove = self.movement[keyname]
- if toMove[1] == 1 and self.cursorX == #self.text[self.cursorY]+1 then
- self:moveTo(1, self.cursorY+1)
- else
- self:move(toMove[1], toMove[2])
- end
- elseif keyname == "enter" then
- local oldLine = self.text[self.cursorY]
- self.text[self.cursorY] = string.sub(oldLine, 1, self.cursorX-1)
- table.insert(self.text, self.cursorY+1, string.sub(oldLine, self.cursorX))
- if self.text[self.cursorY+1] == "" then
- self.text[self.cursorY+1] = string.match(self.text[self.cursorY], "%s*")
- self:moveTo(#self.text[self.cursorY+1]+1, self.cursorY+1)
- else
- self:moveTo(1, self.cursorY+1)
- end
- elseif keyname == "tab" then
- os.queueEvent("char", " ")
- elseif keyname == "end" then
- self.cursorX = #self.text[self.cursorY]+1
- elseif keyname == "home" then
- self.cursorX = 1
- elseif keyname == "delete" then
- self.text[self.cursorY] = string.sub(self.text[self.cursorY], 1, self.cursorX-1)..string.sub(self.text[self.cursorY], self.cursorX+1)
- end
- self:makeTextChangedCallback()
- end,
- onClick = function(self, button, x, y)
- self:moveTo(x, y-self.scrollY)
- end,
- onMouse_scroll = function(self, direction)
- self.scrollY = self.scrollY - direction
- end,
- searchForStrinsToHightlight = function(self, highlightedWords, line, pattern, color, func)
- local lastNumPos = 1
- for num in string.gmatch(line, pattern) do
- local pos = string.find(line, num, lastNumPos, true)
- lastNumPos = pos+1
- if not func or func(pos) then
- table.insert(highlightedWords, {word = num, pos = pos, color = color})
- end
- end
- end,
- drawHightlightedStrings = function(self, x, y, liney, highlightedWords)
- for i, word in ipairs(highlightedWords) do
- if word.pos+#word.word>self.w then
- word.word = string.sub(word.word, 1, self.w-word.pos+1)
- end
- if word.pos<self.w then
- term.setTextColor(word.color)
- term.setCursorPos(x+word.pos-1, y+liney-1)
- term.write(word.word)
- end
- end
- end,
- draw = function(self, x, y)
- if -self.scrollY > #self.text-self.h then self.scrollY = -#self.text+self.h end
- if self.scrollY > 0 then self.scrollY = 0 end
- local y = y + self.scrollY
- local cursorX, cursorY = self.cursorX+x-1, self.cursorY+y-1
- local isMultiLineComment = false
- local isMultiLineString = false
- for liney, line in ipairs(self.text) do
- if liney <= self.h-y+2 and liney > -self.scrollY then
- local lineToWrite = string.sub(line, 1, self.w)
- term.setBackgroundColor(self.color)
- if isMultiLineComment then
- term.setTextColor(self.commentColor)
- elseif isMultiLineString then
- term.setTextColor(self.stringColor)
- else
- term.setTextColor(self.textColor)
- end
- term.setCursorPos(x, y+liney-1)
- term.write(lineToWrite)
- local comments = {}
- self:searchForStrinsToHightlight(comments, line, "%-%-.*", self.commentColor)
- if not isMultiLineComment and not isMultiLineString then
- local highlightedWords = {}
- for i, keyword in ipairs(self.keywords) do
- self:searchForStrinsToHightlight(highlightedWords, line, keyword, self.keywordColor, function(pos)
- local beforeChar, afterChar = string.sub(line, pos-1, pos-1), string.sub(line, pos+#keyword, pos+#keyword)
- return beforeChar == "" or beforeChar == " " and afterChar == "" or afterChar == " "
- end)
- end
- self:searchForStrinsToHightlight(highlightedWords, line, "[%(].*[%)]", self.argumentColor)
- self:searchForStrinsToHightlight(highlightedWords, line, "%[%[\".*", self.stringColor)
- self:searchForStrinsToHightlight(highlightedWords, line, "[%w_%[%]]+[%.%:]%a*[%w_%[%]]", self.tablecallColor)
- self:searchForStrinsToHightlight(highlightedWords, line, "[\"].*[\"]", self.stringColor)
- self:searchForStrinsToHightlight(highlightedWords, line, "['].*[']", self.stringColor)
- self:searchForStrinsToHightlight(highlightedWords, line, "%d", self.numberColor)
- self:drawHightlightedStrings(x, y, liney, highlightedWords)
- end
- self:drawHightlightedStrings(x, y, liney, comments)
- if liney == self.cursorY then
- paintutils.drawPixel(cursorX, cursorY, self.cursorColor)
- -- the cursor is on this line, so we draw the char the cursor is again, but it in a different color
- term.setBackgroundColor(self.cursorColor)
- term.setTextColor(self.textColor)
- term.setCursorPos(cursorX, cursorY)
- term.write(string.sub(line, self.cursorX, self.cursorX))
- end
- if string.find(line, "--[[", 1, true) then
- isMultiLineComment = true
- end
- if not isMultiLineComment and string.find(line, "[[\"", 1, true) then
- isMultiLineString = true
- end
- if string.find(line, "\"]]", 1, true) then
- isMultiLineString = false
- end
- if string.find(line, "]]") then
- isMultiLineComment = false
- end
- end
- end
- end,
- makeTextChangedCallback = function(self)
- if self.onTextChanged then
- self:onTextChanged(self.text)
- end
- end,
- loadFile = function(self, file)
- self.text = {}
- for line, lineNum in io.lines(file) do
- table.insert(self.text, line)
- end
- self.text[1] = self.text[1] or ""
- self.text[2] = self.text[2] or ""
- self.cursorX, self.cursorY = 1, 1
- self:makeTextChangedCallback()
- end,
- },
- paint = {
- canvas = {},
- selectedColors = {colors.black, colors.white},
- onClick = function(self, button, x, y)
- if not self.canvas[x] then self.canvas[x] = {} end
- self.canvas[x][y] = self.selectedColors[button]
- end,
- onMouse_drag = function(self, button, x, y)
- self:onClick(button, x, y)
- end,
- draw = function(self, x, y)
- for pixelX, line in pairs(self.canvas) do
- for pixelY, pixel in pairs(line) do
- paintutils.drawPixel(pixelX+x-1, pixelY+y-1, pixel)
- end
- end
- end,
- loadFile = function(self, file)
- local tColourLookup = {}
- for n=1,16 do
- tColourLookup[ string.byte( "0123456789abcdef",n,n ) ] = 2^(n-1)
- end
- local function getColourOf( char )
- -- Values not in the hex table are transparent (canvas coloured)
- return tColourLookup[char]
- end
- local file = fs.open("/project/Game/Level/Dirt.nfp", "r")
- self.canvas = {{}}
- while true do
- table.insert(self.canvas, {})
- local line = file.read()
- if not line then
- break
- else
- for i = 1, #line do
- local color = getColourOf(string.sub(line, i, i))
- table.insert(self.canvas[#self.canvas], color)
- end
- end
- end
- file.close()
- end
- },
- filesystem = {
- path = "", folderColor = colors.gray, fileColor = colors.lightGray, selectedColor = colors.white,
- fileY = 0, selectedFile = nil, draggingFile = nil,
- goThroughFiles = function(self, dir, func, x, y)
- if fs.getName(dir) ~= "rom" and string.sub(fs.getName(dir), 1, 1) ~= "." then
- local files = fs.list(dir)
- for i, fileName in ipairs(files) do
- self.fileY = self.fileY + 1
- local filePath = fs.combine(dir, fileName)
- func(filePath, x, y+self.fileY)
- if fs.isDir(filePath) then
- self:goThroughFiles(filePath, func, x+1, y)
- end
- end
- end
- end,
- drawDir = function(self, x, y)
- self:goThroughFiles(self.path, function(filePath, x, y)
- if fs.isDir(filePath) then
- term.setTextColor(self.folderColor)
- else
- term.setTextColor(self.fileColor)
- end
- if filePath == self.selectedFile then
- term.setBackgroundColor(self.selectedColor)
- else
- term.setBackgroundColor(self.color)
- end
- term.setCursorPos(x, y)
- term.write(fs.getName(filePath))
- end, x, y)
- end,
- draw = function(self, x, y)
- self.fileY = 0
- self:drawDir(x, y)
- end,
- onClick = function(self, button, mx, my)
- self.fileY = 0
- self:goThroughFiles(self.path, function(filePath, x, y)
- if self.fileY == my-1 then
- self.selectedFile = filePath
- if fs.isDir(filePath) and self.onFolderClicked then
- self:onFolderClicked(filePath)
- elseif not fs.isDir(filePath) and self.onFileClicked then
- self:onFileClicked(filePath)
- end
- end
- end, 0, 0)
- end,
- onMouse_drag = function(self, x, y)
- self.draggingFile = self.selectedFile
- end,
- onMouse_up = function(self, button, x, y)
- local fileToDragOn = self:getFileByNumber(y-1)
- if fileToDragOn and self.draggingFile then
- if not fs.isDir(fileToDragOn) then
- fileToDragOn = fs.getDir(fileToDragOn)
- end
- local destination = fs.combine(fileToDragOn, fs.getName(self.draggingFile))
- if not fs.exists(destination) then
- local succ, mess = pcall(function() fs.move(self.draggingFile, destination) end)
- end
- end
- self.draggingFile = nil
- end,
- getNumberOfFile = function(self, file)
- self.fileY = 0
- local num
- self:goThroughFiles(self.path, function(filePath, x, y)
- if file == filePath then
- num = y
- end
- end, 0, 0)
- return num
- end,
- getFileByNumber = function(self, num)
- self.fileY = 0
- local file
- self:goThroughFiles(self.path, function(filePath, x, y)
- if num == y then
- file = filePath
- end
- end, 0, 0)
- return file
- end,
- getPositionOfFile = function(self, file)
- self.fileY = 0
- local fx, fy
- self:goThroughFiles(self.path, function(filePath, x, y)
- if filePath == file or (type(file) == "number" and y == file) then
- fx, fy = x, y
- end
- end, 0, 0)
- return fx, fy
- end,
- onKey = function(self, key)
- local currentSelectedNum = self:getNumberOfFile(self.selectedFile)
- if currentSelectedNum then
- if key == keys.up then
- self.selectedFile = self:getFileByNumber(currentSelectedNum-1)
- elseif key == keys.down then
- self.selectedFile = self:getFileByNumber(currentSelectedNum+1)
- elseif key == keys.a or key == keys.f then
- local dir
- if fs.isDir(self.selectedFile) then
- dir = self.selectedFile
- else
- dir = fs.getDir(self.selectedFile)
- end
- if key == keys.a then
- local file = fs.open(fs.combine(dir, "New File"), "w")
- file:close()
- self.selectedFile = fs.combine(dir, "New File")
- elseif key == keys.f then
- fs.makeDir(fs.combine(dir, "New Folder"))
- self.selectedFile = fs.combine(dir, "New Folder")
- end
- elseif key == keys.delete then
- fs.delete(self.selectedFile)
- elseif key == keys.r or key == keys.f2 then
- self.selected = false
- self.children.renameInput = ui.new.textinput{
- selected = true, color = self.folderColor, textColor = self.textColor, w = self.w, text = fs.getName(self.selectedFile),
- onFinished = function(textinput, text)
- local destination = fs.combine(fs.getDir(self.selectedFile), text)
- if text ~= "" and not fs.exists(destination) then
- fs.move(self.selectedFile, destination)
- end
- self.selectedFile = destination
- self.children.renameInput = nil
- self.selected = true
- end
- }
- self.children.renameInput.x, self.children.renameInput.y = self:getPositionOfFile(currentSelectedNum)
- self.children.renameInput.x, self.children.renameInput.y = self.children.renameInput.x+1, self.children.renameInput.y+1
- self.children.renameInput.w = #self.children.renameInput.text
- end
- end
- end
- },
- rectangle = {
- draw = function(self, x, y)
- paintutils.drawBox(x, y, x+self.w-1, y+self.h-1)
- end
- }
- }
- ui.new = setmetatable({}, {__index = function(self, elementType)
- return function(args)
- return setmetatable(args, {__index = setmetatable(ui.elements[elementType],{__index = {x = 1, y = 1, w = 1, h = 1, color = colors.gray, textColor = colors.white, children = {}}})})
- end
- end})
- ui.draw = function(elements, parent, x, y)
- local parent = parent or {x = 1, y = 1}
- local x, y = x or parent.x, y or parent.y
- if not parent.w then
- parent.w, parent.h = term.getSize()
- end
- for elementName, element in pairs(elements) do
- paintutils.drawFilledBox(x+element.x-1, y+element.y-1, x+element.x-1+element.w-1, y+element.y-1+element.h-1, element.color)
- term.setCursorPos(x, y)
- term.setBackgroundColor(element.color)
- term.setTextColor(element.textColor)
- if element.draw then
- element:draw(x+element.x-1, y+element.y-1)
- end
- if element.children then
- ui.draw(element.children, element, x+element.x-1, y+element.y-1)
- end
- end
- end
- ui.update = function(elements, events, parent, x, y)
- local event, var1, var2, var3 = events[1], events[2], events[3], events[4]
- local parent = parent or {x = 1, y = 1}
- local x, y = x or parent.x, y or parent.y
- if not parent.w then
- parent.w, parent.h = term.getSize()
- end
- for elementName, element in pairs(elements) do
- term.setCursorPos(element.x, element.y)
- local x, y = parent.x+element.x-1, parent.y+element.y-1
- if event == "mouse_click" and var2 >= x and var3 >= y and var2 < x+element.w and var3 < y+element.h then
- if element.onClick then
- element:onClick(var1, var2-x+1, var3-y+1)
- end
- element.selected = true
- elseif event == "mouse_click" then
- element.selected = false
- end
- local eventMethod = element["on"..string.upper(string.sub(event, 1, 1))..string.sub(event, 2)]
- if element.selected and eventMethod then
- if string.sub(event, 1, #"mouse") == "mouse" then
- eventMethod(element, var1, var2-x+1, var3-y+1)
- else
- eventMethod(element, var1, var2, var3)
- end
- end
- if element.update then
- element:update(x+element.x-1, y+element.y-1, event, var1, var2, var3)
- end
- if element.children then
- ui.update(element.children, events, element, x+element.x-1, y+element.y-1)
- end
- end
- end
- setmetatable(ui.elements, {__newindex = function(self, elementName, elementTable)
- rawset(self, elementName, elementTable)
- _G[elementName] = function(args)
- return ui.new[elementName](args)
- end
- end})
- for elementName, elementTable in pairs(ui.elements) do
- _G[elementName] = function(args)
- return ui.new[elementName](args)
- end
- end
- local w, h = term.getSize()
- local sidebarWidth = math.floor(w/3.5)
- local elements = {}
- elements.editor = textedit{
- x = sidebarWidth+3, y = 2, w = w-sidebarWidth-3, h = h-2, color = colors.black, scrolls = {},
- onTextChanged = function(self, text)
- if self.openFile then
- local file = fs.open(self.openFile, "w")
- for lineNum, line in ipairs(text) do
- file.write(line.."\n")
- end
- file.close()
- end
- end
- }
- elements.filesystem = filesystem{
- x = 2, y = 2, h = h-2, w = sidebarWidth, folderColor = colors.lightGray, fileColor = colors.white, color = colors.black, path = "", selectedColor = colors.gray,
- onFileClicked = function(self, file)
- if elements.editor.openFile then
- elements.editor.scrolls[elements.editor.openFile] = elements.editor.scrollY
- end
- elements.editor.openFile = file
- elements.editor:loadFile(file)
- if not elements.editor.scrolls[file] then elements.editor.scrolls[file] = 0 end
- elements.editor.scollY = elements.editor.scrolls[file]
- elements.editor.selected = true
- elements.filesystem.selected = false
- end
- }
- while true do
- term.setBackgroundColor(colors.gray)
- term.clear()
- ui.draw(elements)
- ui.update(elements, {os.pullEvent()})
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement