Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --[[
- A graphical user interface file browser (guifb)
- Version 1.4.1
- by inventor2514
- ]]--
- if not term.isColor then
- print("An advanced computer is required")
- return
- else
- if not term.isColor() then
- print("An advanced computer is required")
- return
- end
- end
- -- Configuration variables
- local sStartDir = ""
- local sEditPath = "/rom/programs/edit"
- local backMain = colors.lightGray
- local backMenu = colors.lightBlue
- local textMain = colors.black
- local textClose = colors.red
- local textButton = colors.blue
- -- Initialize some variables for later
- local tDirIcon = {"", " /\\____", "| |", "| |", "|______|"}
- local tFileIcon = {" ______", "| |", "| ~~~~ |", "| ~~~~ |", "|______|"}
- local xMax, yMax = term.getSize()
- local row = 4, 3, 1
- local sDir = sStartDir
- local maxCol, maxRow = 1, 1
- local tOrigins = {}
- local tData = {}
- local sClipboard = ""
- -- Returns the maximum columns and rows of icons
- local function iconLimits()
- local i, maxCol = 3, 0
- while i <= xMax-9 do
- i = i + 9
- maxCol = maxCol + 1
- end
- local i, maxRow = 2, 0
- while i <= yMax-6 do
- i = i + 6
- maxRow = maxRow + 1
- end
- return maxCol, maxRow
- end
- -- Returns a table of possible icon origin positions
- local function originTable()
- tOrigins = {}
- for i=1, maxRow do
- for j=1, maxCol do
- table.insert(tOrigins, {3+9*(j-1), 2+6*(i-1)})
- end
- end
- return tOrigins
- end
- -- Returns a table containing file data in {sName, bDir} format
- local function fileData(sDir)
- local tList = fs.list(sDir)
- local tData = {}
- for i,sName in ipairs(tList) do
- if string.sub(sName, 1, 1) ~= "." then
- local sPath = fs.combine(sDir, sName)
- table.insert(tData, {sName, fs.isDir(sPath)})
- end
- end
- return tData
- end
- -- Writes text to the specified position
- local function output(x, y, sText, color)
- if color then
- term.setTextColor(color)
- else
- term.setTextColor(textMain)
- end
- term.setCursorPos(x, y)
- term.write(sText)
- end
- -- Draws a rectangular border
- local function drawBorder(x, y, xLen, yLen)
- output(x, y, "/")
- output(x+xLen-1, y, "\\")
- output(x, y+yLen-1, "\\")
- output(x+xLen-1, y+yLen-1, "/")
- for i=x+1, x+xLen-2 do
- output(i, y, "-")
- output(i, y+yLen-1, "-")
- end
- for i=y+1, y+yLen-2 do
- output(x, i, "|")
- output(x+xLen-1, i, "|")
- end
- end
- -- Draws a window-like border and buttons
- local function drawMainBorder()
- drawBorder(1, 1, xMax, yMax)
- output(xMax-4, 1, "X", textClose)
- output(xMax-6, 1, "<", textButton)
- output(xMax, 3, "*", textButton)
- output(xMax, yMax-2, "*", textButton)
- output(3, 1, "[SublimeOS]", textButton)
- end
- -- Draws an icon at the specified position
- local function drawIcon(x, y, tIcon, sName)
- local tIcon = tIcon
- for i, s in ipairs(tIcon) do
- output(x, y+i-1, s)
- end
- if sName then output(x, y+#tIcon, sName) end
- end
- -- Draws icons to represent file data
- local function drawIcons()
- local pos = 1 + maxCol*(row-1)
- local limit = pos-1+maxCol*maxRow
- if #tData < limit then limit = #tData end
- local icon = 1
- for i = pos, limit do
- local x, y, sName = tOrigins[icon][1], tOrigins[icon][2], string.sub(tData[i][1], 1, 8)
- if tData[i][2] then
- drawIcon(x, y, tDirIcon, sName)
- else
- drawIcon(x, y, tFileIcon, sName)
- end
- icon = icon + 1
- end
- end
- -- Draws a centered menu and returns origin, length, and height
- local function drawMenu(tMenu)
- term.setBackgroundColor(backMenu)
- local length, height = 0, #tMenu+2
- for _, sLine in ipairs(tMenu) do
- if string.len(sLine) > length then
- length = string.len(sLine)+2
- end
- end
- local sBlank = ""
- for i=1, length-2 do sBlank = sBlank.." " end
- local x, y = math.floor(xMax/2) - math.ceil(length/2), math.floor(yMax/2) - math.ceil(#tMenu/2)
- drawBorder(x, y, length, height)
- for i, sLine in ipairs(tMenu) do
- output(x+1, y+i, sBlank)
- output(x+1, y+i, sLine)
- end
- return {x, y}, length, height
- end
- -- Runs a selection menu and returns a number or nil
- local function runSelectionMenu(...)
- local tArgs = {...}
- local tMenu = {}
- for _, sOption in ipairs(tArgs) do
- table.insert(tMenu, " ( ) "..sOption.." ")
- end
- table.insert(tMenu, " [Okay] [Cancel] ")
- local origin, length, height = drawMenu(tMenu)
- local selection = 1
- local x, y = origin[1]+3, origin[2]+1
- local bMenu = true
- while bMenu do
- output(origin[1]+3, origin[2]+selection, "#")
- local sEvent, ret1, ret2, ret3 = os.pullEventRaw()
- if sEvent == "mouse_click" and ret1 == 1 then
- local x, y = ret2, ret3
- if x > origin[1] and x < origin[1]+length-1 and y > origin[2] and y < origin[2]+height-1 then
- if y < origin[2]+height-2 then
- selection = y - origin[2]
- elseif x > origin[1]+1 and x < origin[1]+8 then
- bMenu = false
- elseif x > origin[1]+8 and x < origin[1]+17 then
- bMenu = false
- selection = nil
- end
- drawMenu(tMenu)
- end
- end
- end
- return selection
- end
- -- Runs a text menu and returns a string
- local function runTextMenu(sPrompt, sStartText)
- local tMenu = {" "..sPrompt..":", " { } ", " [Done] "}
- local origin, length, height = drawMenu(tMenu)
- local sText = ""
- if sStartText then sText = sStartText end
- local bMenu = true
- while bMenu do
- output(origin[1]+3, origin[2]+2, string.sub(sText, 1, 14))
- output(origin[1]+3, origin[2]+2, " ")
- output(origin[1]+3, origin[2]+2, string.sub(sText, -14))
- local sEvent, ret1, ret2, ret3 = os.pullEventRaw()
- if sEvent == "mouse_click" and ret1 == 1 then
- local x, y = ret2, ret3
- if y == origin[2]+height-2 and x > origin[1]+1 and x < origin[1]+8 then
- bMenu = false
- end
- elseif sEvent == "char" then
- sText = sText .. ret1
- elseif sEvent == "key" then
- if ret1 == 14 then
- sText = string.sub(sText, 1, string.len(sText)-1)
- end
- end
- end
- return sText
- end
- -- Runs a confirmation menu and returns a boolean
- local function runConfirmMenu(...)
- local tArgs = {...}
- local tMenu = {}
- for _, sLine in ipairs(tArgs) do
- tMenu[#tMenu+1] = " "..sLine.." "
- end
- table.insert(tMenu, " [Yes] [No] ")
- local origin, length, height = drawMenu(tMenu)
- local bMenu, bConfirm = true
- while bMenu do
- local sEvent, ret1, ret2, ret3 = os.pullEventRaw()
- if sEvent == "mouse_click" and ret1 == 1 then
- local x, y = ret2, ret3
- if y == origin[2]+height-2 and x > origin[1]+1 and x < origin[1]+7 then
- bMenu, bConfirm = false, true
- elseif y == origin[2]+height-2 and x > origin[1]+7 and x < origin[1]+12 then
- bMenu, bConfirm = false, false
- end
- end
- end
- return bConfirm
- end
- -- Redraws the border and icons
- local function redraw()
- term.setBackgroundColor(backMain)
- term.clear()
- drawIcons()
- drawMainBorder()
- end
- -- Recalculate the file data and icon variables
- local function recalculate()
- row = 1
- tData = fileData(sDir)
- maxCol, maxRow = iconLimits()
- tOrigins = originTable()
- end
- -- Returns the data associated with an icon or nil
- local function iconData(x, y)
- local pos = maxCol*(row-1)
- for i=1, maxCol*maxRow do
- local xMin, yMin = tOrigins[i][1], tOrigins[i][2]
- if x >= xMin and y >= yMin and x <= xMin+8 and y <= yMin+5 then
- tIconData = tData[pos+i]
- if tIconData then
- if fs.exists(fs.combine(sDir, tIconData[1])) then
- return tIconData
- else
- recalculate()
- redraw()
- end
- end
- end
- end
- return nil
- end
- -- Main program loop
- local bRun = true
- recalculate()
- redraw()
- local bCursorToggle = false
- while bRun do
- local sEvent, ret1, ret2, ret3 = os.pullEventRaw()
- if sEvent == "mouse_click" then
- local x, y = ret2, ret3
- -- left-click
- if ret1 == 1 then
- -- close button
- if x == xMax-4 and y == 1 then
- bRun = false
- -- back button
- elseif x == xMax-6 and y == 1 then
- if sDir ~= "" then
- sDir = fs.combine(sDir, "..")
- recalculate()
- redraw()
- end
- -- scroll up button
- elseif x == xMax and y == 3 then
- if row > 1 then
- row = row - 1
- redraw()
- end
- -- scroll down button
- elseif x == xMax and y == yMax-2 then
- if row < (math.ceil(#tData/maxCol)-(maxRow-1)) then
- row = row + 1
- redraw()
- end
- -- file/dir icon
- elseif iconData(x, y) then
- local tIconData = iconData(x, y)
- if tIconData[2] then
- sDir = fs.combine(sDir, tIconData[1])
- recalculate()
- redraw()
- else
- local sPath = "/" .. fs.combine(sDir, tIconData[1])
- shell.run(sEditPath, sPath)
- redraw()
- end
- end
- -- right-click
- elseif ret1 == 2 then
- if x == 1 or y == 1 or x == xMax or y == yMax then
- -- do nothing
- elseif iconData(x, y) then
- local tIconData = iconData(x, y)
- if tIconData[2] then
- local sDiskSide = nil
- for i,sSide in ipairs( rs.getSides() ) do
- if disk.isPresent(sSide) then
- if tIconData[1] == disk.getMountPath(sSide) then
- sDiskSide = sSide
- end
- end
- end
- if sDiskSide then
- local selection = runSelectionMenu("Enter Disk", "Label Disk", "Copy Disk", "Eject Disk")
- if selection and fs.exists(fs.combine(sDir, tIconData[1])) then
- -- enter disk
- if selection == 1 then
- sDir = fs.combine(sDir, tIconData[1])
- recalculate()
- redraw()
- -- label disk
- elseif selection == 2 then
- local sLabel = runTextMenu("Disk Label", disk.getLabel(sDiskSide))
- if sLabel ~= "" and disk.isPresent(sDiskSide) then
- disk.setLabel(sDiskSide, sLabel)
- end
- -- copy disk
- elseif selection == 3 then
- if fs.exists(".copy") then fs.delete(".copy") end
- fs.copy(fs.combine(sDir, tIconData[1]), ".copy")
- sClipboard = tIconData[1]
- -- eject disk
- elseif selection == 4 then
- disk.eject(sDiskSide)
- sleep(.3)
- fs.delete(sDiskSide)
- recalculate()
- redraw()
- end
- end
- else
- local selection = runSelectionMenu("Open Dir", "Rename Dir", "Copy Dir", "Delete Dir")
- if selection then
- -- enter dir
- if selection == 1 then
- sDir = fs.combine(sDir, tIconData[1])
- recalculate()
- redraw()
- -- rename dir
- elseif selection == 2 then
- if not fs.isReadOnly(fs.combine(sDir, tIconData[1])) then
- local sName = runTextMenu("Dir Name", tIconData[1])
- if sName ~= "" and sName ~= tIconData[1] and not fs.isReadOnly(fs.combine(sDir, sName)) then
- local bConfirm = true
- if fs.exists(fs.combine(sDir,sName)) then
- bConfirm = runConfirmMenu("Overwrite existing", "file with that name?")
- end
- if bConfirm then
- fs.move(fs.combine(sDir, tIconData[1]), fs.combine(sDir, sName))
- recalculate()
- end
- end
- end
- -- copy dir
- elseif selection == 3 then
- if fs.exists(".copy") then fs.delete(".copy") end
- fs.copy(fs.combine(sDir, tIconData[1]), ".copy")
- sClipboard = tIconData[1]
- -- delete dir
- elseif selection == 4 then
- if not fs.isReadOnly(fs.combine(sDir, tIconData[1])) then
- fs.delete(fs.combine(sDir, tIconData[1]))
- recalculate()
- end
- end
- end
- end
- else
- local selection = runSelectionMenu("Edit File", "Run as Script", "Rename File", "Copy File", "Delete File")
- if selection then
- -- edit file
- if selection == 1 then
- local sPath = "/" .. fs.combine(sDir, tIconData[1])
- shell.run(sEditPath, sPath)
- -- run file as script
- elseif selection == 2 then
- local sPath = "/" .. fs.combine(sDir, tIconData[1])
- local sArgs = runTextMenu("Parameters")
- term.setBackgroundColor(colors.black)
- term.clear()
- term.setCursorPos(1, 1)
- if sArgs ~= "" then
- local tArgs = {}
- for sMatch in string.gmatch(sArgs, "[^ ]+") do
- table.insert(tArgs, sMatch)
- end
- shell.run(sPath, unpack(tArgs))
- else
- shell.run(sPath)
- end
- sleep(2)
- print("= Press any key to return =")
- os.pullEventRaw("key")
- -- rename file
- elseif selection == 3 then
- if not fs.isReadOnly(fs.combine(sDir, tIconData[1])) then
- local sName = runTextMenu("File Name", tIconData[1])
- if sName ~= "" and sName ~= tIconData[1] and not fs.isReadOnly(fs.combine(sDir, sName)) then
- local bConfirm = true
- if fs.exists(fs.combine(sDir,sName)) then
- bConfirm = runConfirmMenu("Overwrite existing", "file with that name?")
- end
- if bConfirm then
- fs.move(fs.combine(sDir, tIconData[1]), fs.combine(sDir, sName))
- recalculate()
- end
- end
- end
- -- copy file
- elseif selection == 4 then
- if fs.exists(".copy") then fs.delete(".copy") end
- fs.copy(fs.combine(sDir, tIconData[1]), ".copy")
- sClipboard = tIconData[1]
- -- delete file
- elseif selection == 5 then
- if not fs.isReadOnly(fs.combine(sDir, tIconData[1])) then
- fs.delete(fs.combine(sDir, tIconData[1]))
- recalculate()
- end
- end
- end
- end
- else
- local selection = runSelectionMenu("New Dir", "New File", "Set Shell Dir", "Paste")
- if selection then
- -- new dir
- if selection == 1 then
- local sName = runTextMenu("Dir Name")
- if sName ~= "" and not fs.isReadOnly(fs.combine(sDir, sName)) then
- local bConfirm = true
- if fs.exists(fs.combine(sDir,sName)) then
- bConfirm = runConfirmMenu("Overwrite existing", "file with that name?")
- end
- if bConfirm then
- fs.makeDir(fs.combine(sDir,sName))
- recalculate()
- end
- end
- -- new file
- elseif selection == 2 then
- local sName = runTextMenu("File Name")
- if sName ~= "" and not fs.isReadOnly(fs.combine(sDir, sName)) then
- local bConfirm = true
- if fs.exists(fs.combine(sDir,sName)) then
- bConfirm = runConfirmMenu("Overwrite existing", "file with that name?")
- end
- if bConfirm then
- local file = io.open(fs.combine(sDir, sName), "w")
- file:write("\n")
- file:close()
- recalculate()
- end
- end
- -- set shell dir
- elseif selection == 3 then
- shell.setDir(sDir)
- -- paste
- elseif selection == 4 then
- local sName = runTextMenu("Paste Name", sClipboard)
- if sName ~= "" and not fs.isReadOnly(fs.combine(sDir, sName)) then
- local bConfirm = true
- if fs.exists(fs.combine(sDir,sName)) then
- bConfirm = runConfirmMenu("Overwrite existing", "file with that name?")
- end
- if bConfirm then
- fs.delete(fs.combine(sDir, sName))
- fs.copy(".copy", fs.combine(sDir, sName))
- recalculate()
- end
- end
- end
- end
- end
- redraw()
- -- middle click
- elseif ret1 ==3 then
- if sDir ~= "" then
- sDir = fs.combine(sDir, "..")
- recalculate()
- redraw()
- end
- end
- elseif sEvent == "mouse_scroll" then
- -- scroll down
- if ret1 == 1 then
- if row < (math.ceil(#tData/maxCol)-(maxRow-1)) then
- row = row + 1
- redraw()
- end
- -- scroll up
- else
- if row > 1 then
- row = row - 1
- redraw()
- end
- end
- elseif sEvent == "key" then
- local key = ret1
- -- page up "scroll up"
- if key == 201 then
- if row > 1 then
- row = row - 1
- redraw()
- end
- -- page down "scroll down"
- elseif key == 209 then
- if row < (math.ceil(#tData/maxCol)-(maxRow-1)) then
- row = row + 1
- redraw()
- end
- -- backspace "back"
- elseif key == 14 then
- if sDir ~= "" then
- sDir = fs.combine(sDir, "..")
- recalculate()
- redraw()
- end
- -- end "close"
- elseif key == 207 then
- bRun = false
- end
- end
- end
- -- Cleanup
- if fs.exists(".copy") then fs.delete(".copy") end
- term.setBackgroundColor(colors.black)
- term.clear()
- term.setCursorPos(1, 1)
Advertisement
Add Comment
Please, Sign In to add comment