local terminal = term.current() local deskIcons = lUtils.asset.load("LevelOS/assets/Desktop_Icons.limg") local desktop = {} local idReference = {} local fc = fs.combine local function locateEntry(tTable,tEntry) if type(tTable) ~= "table" then error("Invalid input #1",2) end for t=1,#tTable do if tTable[t] == tEntry then return true,t end end return false,0 end local fileTypes if fs.exists("LevelOS/data/formats.lconf") then fileTypes = lUtils.asset.load("LevelOS/data/formats.lconf") end if not fileTypes then local copy = lUtils.instantiate fileTypes = { _VERSION="1.3", [""] = { name="File", program="Lua", contextMenu={ {"Execute","Edit"}, {"Lua","rom/programs/edit.lua"} }, openWith={ "Lua", "rom/programs/edit.lua" }, icon=deskIcons[1] }, lua = { name="Lua script", program="Lua", contextMenu={ {"Execute","Edit"}, {"Lua","rom/programs/edit.lua"} }, openWith={ "Lua", "rom/programs/edit.lua" }, icon=deskIcons[2], emptyFilePreset="" }, txt = { name="Text file", program="LevelOS/notepad.lua", contextMenu={ {"Edit"}, {"LevelOS/notepad.lua"} }, openWith={ "LevelOS/notepad.lua", "rom/programs/edit.lua" }, icon=deskIcons[5], emptyFilePreset="" }, lconf = { name="Config file", program="LevelOS/notepad.lua", contextMenu={ {"Edit"}, {"LevelOS/notepad.lua"} }, openWith={ "LevelOS/notepad.lua", "rom/programs/edit.lua" }, icon=deskIcons[6], emptyFilePreset="{}" }, sgui = { name="Shapescape GUI", program="Program_Files/Shapescape", contextMenu={ {"Open","Execute"}, {"Program_Files/Shapescape","Lua"} }, openWith={ "Lua", "Program_Files/Shapescape", "rom/programs/edit.lua" }, icon=deskIcons[8], emptyFilePreset="return {assets={},slides={{contextMenu=1,objs={},w=51,h=19}}}" }, sml = { name="SML Document", program="Program_Files/sml", contextMenu={ {"Open","Edit"}, {"Program_Files/sml","rom/programs/edit.lua"} }, openWith={ "Program_Files/sml", "rom/programs/edit.lua" }, icon=deskIcons[9], emptyFilePreset="" }, limg = { name="Image", program="LevelOS/imageviewer.lua", contextMenu={ {"View","Edit"}, {"LevelOS/imageviewer.lua","rom/programs/edit.lua"} }, openWith={ "LevelOS/imageviewer.lua", "rom/programs/edit.lua" }, icon=copy(deskIcons[10]) }, bimg = { name="Image", program="LevelOS/imageviewer.lua", contextMenu={ {"View","Edit"}, {"LevelOS/imageviewer.lua","rom/programs/edit.lua"} }, openWith={ "LevelOS/imageviewer.lua", "rom/programs/edit.lua" }, icon=copy(deskIcons[10]) }, nfp = { name="NFP Image", program="LevelOS/imageviewer.lua", contextMenu={ {"View","Edit"}, {"LevelOS/imageviewer.lua","rom/programs/fun/advanced/paint.lua"} }, openWith={ "LevelOS/imageviewer.lua", "rom/programs/fun/advanced/paint.lua", "rom/programs/edit.lua" }, icon=copy(deskIcons[10]), emptyFilePreset="" }, nfg = { name="Animation", program="LevelOS/imageviewer.lua", contextMenu={ {"View","Edit"}, {"LevelOS/imageviewer.lua","rom/programs/edit.lua"} }, openWith={ "LevelOS/imageviewer.lua", "rom/programs/edit.lua" }, icon=copy(deskIcons[10]) }, } lUtils.asset.save(lUtils.instantiate(fileTypes),"LevelOS/data/formats.lconf", false) end if fileTypes._VERSION == "1.0" then for k,v in pairs(fileTypes) do if type(v) == "table" then v.name = v.name or v.n v.n = nil v.program = v.program or v.p v.p = nil v.icon = v.icon or v.i v.i = nil v.contextMenu = v.contextMenu or v.c v.c = nil v.openWith = v.openWith or v.o v.o = nil v.emptyFilePreset = v.emptyFilePreset or v.e end end fileTypes._VERSION = "1.1" fileTypes["llnk"] = {name="Shortcut",program="Lua"} lUtils.asset.save(lUtils.instantiate(fileTypes),"LevelOS/data/formats.lconf") end if fileTypes._VERSION == "1.1" then for k,v in pairs(fileTypes) do if type(v) == "table" then v._VERSION = nil end end for k,v in pairs(fileTypes.nfp.openWith) do if v == "rom/programs/fun/paint.lua" then fileTypes.nfp.openWith[k] = "rom/programs/fun/advanced/paint.lua" end end fileTypes._VERSION = "1.2" lUtils.asset.save(lUtils.instantiate(fileTypes),"LevelOS/data/formats.lconf",false) end if fileTypes._VERSION == "1.2" then fileTypes.bimg = { name="Image", program="LevelOS/imageviewer.lua", contextMenu={ {"View","Edit"}, {"LevelOS/imageviewer.lua","rom/programs/edit.lua"} }, openWith={ "LevelOS/imageviewer.lua", "rom/programs/edit.lua" }, icon=deskIcons[10] } fileTypes._VERSION = "1.3" lUtils.asset.save(lUtils.instantiate(fileTypes),"LevelOS/data/formats.lconf",false) end local dConfig if not lOS.explorer then lOS.explorer = {} end lOS.explorer.shortcache = {} lOS.explorer.imgcache = {} lOS.explorer.nimgcache = {} lOS.explorer.desktopBackground = nil lOS.fClipboard = {} local disks = {} lOS.explorer.disks = disks local function reloadDisks() for k,v in pairs(disks) do disks[k] = nil end local ndisks = {peripheral.find("drive",function(name,object) return object.hasData() end)} for t=1,#ndisks do ndisks[ndisks[t].getMountPath()] = ndisks[t] end for k,v in pairs(ndisks) do disks[k] = v end end reloadDisks() local function getName(path) local isDisk = false if disks[path] and disks[path].getDiskLabel() then str = disks[path].getDiskLabel().." ("..string.gsub(path,"_"," ")..")" isDisk = true elseif path == "" then str = "Local disk" else str = string.gsub(fs.getName(path),"_"," ") if lUtils.getFileType(str) == ".llnk" then str = str:sub(1,#str-5) end end return str,isDisk end lOS.explorer.getName = getName local symbols = { ["User/Cloud"] = {symbol="",color=colors.blue}, [""] = {symbol="",color=colors.lightGray}, ["rom"] = {symbol="",color=colors.red}, ["User"] = {symbol="",color=colors.lightBlue}, ["User/Desktop"] = {symbol="",color=colors.lightBlue}, ["User/Documents"] = {symbol="",color=colors.lightGray}, ["User/Downloads"] = {symbol="",color=colors.blue}, ["User/Images"] = {symbol="",color=colors.lightBlue}, ["User/Scripts"] = {symbol="",color=colors.cyan}, ["User/Games"] = {symbol="",color=colors.lightGray}, ["User/Music"] = {symbol="",color=colors.blue}, } lOS.explorer.getIcon = function(path) local disks = {peripheral.find("drive",function(name,object) return object.hasData() end)} for t=1,#disks do disks[disks[t].getMountPath()] = disks[t] end if symbols[path] then return symbols[path].symbol, symbols[path].color elseif disks[path] then return "", colors.blue elseif fs.isDir(path) then return "\143", colors.yellow else return "\143", colors.white end end local function genFile(f) if not fs.exists(f) then error(f.." does not exist",2) end local file = {path=f,name=fs.getName(f),type=lUtils.getFileType(f):sub(2),readOnly=fs.isReadOnly(f),isDir=fs.isDir(f)} if not ((file.isDir and file.readOnly) or disks[file.path]) then local a = fs.attributes(f) for k,v in pairs(a) do file[k] = v end end return file end local function uFP(filepath2) -- unique filepath if fs.exists(filepath2) == true then t = 1 while fs.exists(string.sub(filepath2,1,string.len(filepath2)-string.len(lUtils.getFileType(filepath2))).."_("..t..")"..lUtils.getFileType(filepath2)) == true do t = t+1 end filepath2 = string.sub(filepath2,1,string.len(filepath2)-string.len(lUtils.getFileType(filepath2))).."_("..t..")"..lUtils.getFileType(filepath2) end return filepath2 end lOS.explorer.uFP = uFP function lOS.genIco(path) local name = getName(path) if fs.isDir(path) and fs.exists(fs.combine(path,"main.lua")) then path = fs.combine(path,"main.lua") end local pth = fs.combine("User/Desktop",name..".llnk") lUtils.asset.save({path},pth) os.queueEvent("explorer_reload") end local presetIcons = { ["User"] = deskIcons[12], ["User/Desktop"] = deskIcons[13], ["User/Documents"] = deskIcons[14], ["User/Downloads"] = deskIcons[15], ["User/Games"] = deskIcons[16], ["User/Images"] = deskIcons[17], ["User/Music"] = deskIcons[18], ["User/Scripts"] = deskIcons[19], ["User/Cloud"] = deskIcons[20], ["rom"] = deskIcons[21], } function lOS.explorer.drawIcon(path,fx,fy,onlyIcon,transparent,maxLines,shortcutIcon) --local file = {path=path,type=lUtils.getFileType(path):sub(2)} local ok,file = pcall(genFile,path) if not ok then lUtils.renderImg(deskIcons[11],fx+2,fy+1,nil,transparent) return end local bg = term.getBackgroundColor() local fg = term.getTextColor() local cTerm = term.current() local isCut = false if lOS.fCut then isCut = locateEntry(lOS.fCut,file.path) end local shortcache = lOS.explorer.shortcache local imgcache = lOS.explorer.imgcache local nimgcache = lOS.explorer.nimgcache local fc = fs.combine local rPath = path local rType = file.type local isShort = false local lines = lUtils.wordwrap(lUtils.getFileName(file.path),7) local lineH = math.min(#lines,4) local fw,fh = 7,5 if #lines > lineH then lines[4] = lines[4]:sub(1,5)..".." end fh = math.max(4+lineH,fh) if not transparent then lOS.boxClear(fx,fy,fx+7-1,fy+5-1+lineH-1) end if shortcache[file.path] then isShort = true rPath = shortcache[file.path][1] rType = lUtils.getFileType(rPath):sub(2) elseif file.type == "llnk" then local info = lUtils.asset.load(file.path) if info and type(info[1]) == "string" then isShort = true rPath = info[1] if not fs.exists(rPath) then imgcache[file.path] = {} for i=0,15 do imgcache[file.path][i] = deskIcons[4] end else rType = lUtils.getFileType(info[1]):sub(2) imgcache[file.path] = {} for i=0,15 do imgcache[file.path][i] = info.icon end end shortcache[file.path] = info end end local pFolder = fs.getDir(rPath) if not isCut then if not fs.exists(rPath) then lUtils.renderImg(deskIcons[4],fx+2,fy+1,nil,transparent) elseif presetIcons[rPath] then lUtils.renderImg(presetIcons[rPath],fx+2,fy+1,nil,transparent) elseif imgcache[file.path] and imgcache[file.path][bg] then local win = imgcache[file.path][bg] if win.reposition then for t=1,3 do term.setCursorPos(fx+2,fy+t) term.blit(win.getLine(t)) end else lUtils.renderImg(win,fx+2,fy+1,nil,transparent) end elseif fs.getName(rPath) == "main.lua" --[[and fs.exists(fc(pFolder,"icon.limg"))]] then if not nimgcache[file.path] and (fs.exists(fc(pFolder,"icon.limg")) or fs.exists(fc(pFolder,"icon.bimg"))) then local img if fs.exists(fc(pFolder,"icon.limg")) then img = lUtils.asset.load(fc(pFolder,"icon.limg")) else img = lUtils.asset.load(fc(pFolder,"icon.bimg")) end img = img[1] local iw = #img[1][1] local ih = #img if iw <= 3 and ih <= 3 then --[[local tWin = window.create(cTerm,fx+2,fy+1,iw,ih,true) term.redirect(tWin) lUtils.renderImg(img,1,1) term.redirect(cTerm) imgcache[file.path] = tWin]] if not imgcache[file.path] then imgcache[file.path] = {} end imgcache[file.path][bg] = img lUtils.renderImg(img,fx+2,fy+1,nil,transparent) else nimgcache[file.path] = true end else lUtils.renderImg(deskIcons[3],fx+2,fy+1,nil,transparent) end elseif fs.isDir(rPath) then if not nimgcache[file.path] and (fs.exists(fc(rPath,"icon.limg")) or fs.exists(fc(rPath,"icon.bimg"))) and fs.exists(fc(rPath,"main.lua")) then local img if fs.exists(fc(rPath,"icon.limg")) then img = lUtils.asset.load(fc(rPath,"icon.limg")) else img = lUtils.asset.load(fc(rPath,"icon.bimg")) end img = img[1] local iw = #img[1][1] local ih = #img if iw <= 3 and ih <= 3 then local tWin = window.create(cTerm,fx+2,fy+1,iw,ih,true) term.redirect(tWin) if transparent then for y=1,2 do local line = {cTerm.getLine(fy+y)} for t=1,3 do line[t] = line[t]:sub(fx+2,fx+4) end term.setCursorPos(1,y) term.blit(unpack(line)) end else term.setBackgroundColor(bg) term.clear() end lUtils.renderImg(img,1,1,nil,transparent) term.setBackgroundColor(colors.yellow) term.setCursorPos(1,3) term.write(" ") term.redirect(cTerm) if not imgcache[file.path] then imgcache[file.path] = {} end imgcache[file.path][bg] = tWin else nimgcache[file.path] = true end else lUtils.renderImg(deskIcons[7],fx+2,fy+1,nil,transparent) end elseif ((rType == "limg" or file.type == "bimg") and lUtils.asset.load(rPath)) or rType == "nfp" then local iw,ih local img if rType == "nfp" then img = lUtils.fread(rPath) ih = 0 iw = 0 for line in img:gmatch("([^\n]*)\n?") do iw = math.max(iw,#line) ih = ih+1 end else img = lUtils.asset.load(rPath) img = img[1] iw = #img[1][1] ih = #img end local tWin = window.create(cTerm,1,1,iw,ih,false) term.redirect(tWin) term.setBackgroundColor(bg) term.clear() lUtils.renderImg(img,1,1) term.redirect(cTerm) if not imgcache[file.path] then imgcache[file.path] = {} end if iw <= 3 and ih <= 3 then imgcache[file.path][bg] = img lUtils.renderImg(img,fx+2,fy+1,nil,transparent) else local lWin = lUtils.littlewin(tWin,6,math.floor(9*(ih/iw)+0.5)) local fWin = window.create(cTerm,fx+2,fy+1,3,3,true) --_G.debuglwin[file.path] = {lWin=lWin,tWin=tWin,img=img} term.redirect(fWin) local win = blittle.createWindow(fWin,1,1,3,3,true) term.redirect(win) if transparent then for y=1,3 do local line = {cTerm.getLine(fy+y)} for t=1,3 do line[t] = line[t]:sub(fx+2,fx+4) end term.setCursorPos(1,y) term.blit(unpack(line)) end else term.setBackgroundColor(bg) term.clear() end lWin.render(1,1) term.redirect(fWin) win.redraw() term.redirect(cTerm) fWin.redraw() imgcache[file.path][bg] = fWin end elseif fileTypes[rType] and fileTypes[rType].icon then lUtils.renderImg(fileTypes[rType].icon,fx+2,fy+1,nil,transparent) else lUtils.renderImg(deskIcons[4],fx+2,fy+1,nil,transparent) end if shortcutIcon then if isShort and not onlyIcon then term.setCursorPos(fx+2,fy+3) term.blit(unpack(shortcutIcon)) elseif lOS.cloud and lOS.cloud.lastSync and lOS.cloud.files and lOS.cloud.files[file.path] then term.setCursorPos(fx+2,fy+3) local pix = {lUtils.getPixel(term.current(),fx+2,fy+3)} term.setBackgroundColor(lUtils.toColor(pix[3])) if lOS.cloud.conflicts[file.path] then term.setTextColor(colors.red) term.write("×") elseif file.modification > lOS.cloud.lastSync then term.setTextColor(colors.blue) term.write("\24") else term.setTextColor(colors.lime) term.write("\7") end end end end term.setBackgroundColor(bg) term.setTextColor(fg) if not onlyIcon then if maxLines then lineH = math.min(maxLines,lineH) end for l=1,lineH do local line = lines[l]:gsub("%s+$","") term.setCursorPos(fx+math.floor(fw/2-#line/2),fy+3+l) if transparent then lUtils.transWrite(line,(not dConfig.textColor)) else term.write(line) end end end return fh end dConfig = {_VERSION=1,files={},sizes={},shortcutIcon=true,background={color=colors.white}} if fs.exists("LevelOS/data/desktop.lconf") then dConfig = lUtils.asset.load("LevelOS/data/desktop.lconf") end if not dConfig._VERSION then -- backup n shit if fs.exists("LevelOS/data/olddesktop.lconf") then fs.delete("LevelOS/data/olddesktop.lconf") end fs.move("LevelOS/data/desktop.lconf","LevelOS/data/olddesktop.lconf") dConfig = {_VERSION=1,files={},sizes={},shortcutIcon=true,background={color=colors.white}} end lOS.explorer.desktopConfig = dConfig function lOS.save() lUtils.asset.save(dConfig,"LevelOS/data/desktop.lconf") lUtils.fwrite("LevelOS/data/settings.lconf",textutils.serialize(lOS.settings)) return true end if not fs.exists("User/Desktop") then fs.makeDir("User/Desktop") -- my PC lUtils.asset.save( { "Program_Files/LevelOS/Explorer/main.lua", icon = { { "—ƒ”", "ff ", " f", }, { "ƒŽ", "f f", " f ", }, { "‚ƒ", "fff", " ", } }, }, "User/Desktop/My_PC.llnk" ) -- shell lUtils.asset.save( { "rom/programs/shell.lua", icon = { { "‡ƒ‹", " ", "fff", }, { "„", "f44", "4ff", }, { "‹‡", "fff", " ", } }, }, "User/Desktop/Shell.llnk" ) local function makeShortcuts(folder) local ls = fs.list(folder) for i,f in ipairs(ls) do local path = fc(folder,f) if fs.isDir(path) then if fs.exists(fc(path,"main.lua")) then lUtils.asset.save({fc(path,"main.lua")},fc("User/Desktop",fs.getName(f))..".llnk") else makeShortcuts(path) end end end end makeShortcuts("Program_Files") end -- dConfig should be loaded after this local currentID = 1 if not dConfig.files then dConfig.files = {} end for id,path in pairs(dConfig.files) do if id >= currentID then currentID = id+1 end idReference[path] = id end local desktopMap = setmetatable({}, { __index = function(self, id) local default = {} self[id] = default return default end }) _G.debugdesktopmap = desktopMap local function clearDesktopMap() for k,v in pairs(desktopMap) do desktopMap[k] = nil end end local function getDesktopSize() local w,h = term.getSize() if lOS.tbSize then h = h - lOS.tbSize end local deskW,deskH = math.floor((w+1)/8),math.floor(h/5) return deskW,deskH end local currentSize do local desktopWidth,desktopHeight = getDesktopSize() currentSize = desktopWidth..","..desktopHeight end if not dConfig.sizes[currentSize] then dConfig.sizes[currentSize] = {} end local function reloadDesktop() if not fs.exists("User/Desktop") then fs.makeDir("User/Desktop") end local desktopFiles = fs.list("User/Desktop") local changed = false for f=1,#desktopFiles do local name = desktopFiles[f] if not idReference[name] then idReference[name] = currentID dConfig.files[currentID] = name currentID = currentID+1 changed = true end end if changed then lUtils.asset.save(dConfig,"LevelOS/data/desktop.lconf") end -- i only need to store position, but if i store them based on names everything gets messed up if a file gets renamed... -- iterate through IDs too to see if theres a file there that doesnt exist anymore wait nah just do in the thing actually wait hmm end reloadDesktop() local function drawBackground(background) for i=0,15 do term.setPaletteColor(2^i,term.nativePaletteColor(2^i)) end if not background then term.setBackgroundColor(colors.white) term.clear() elseif background.path and fs.exists(background.path) then local col = background.color or colors.white local tw,th = term.getSize() local rImg local img local w,h local t = lUtils.getFileType(background.path) if t == ".bimg" or t == ".limg" or t == ".nfg" then img = lUtils.asset.load(background.path) rImg = img[1] w = #rImg[1][1] h = #rImg elseif t == ".nfp" then rImg = lUtils.fread(background.path) h = 0 w = 0 local emptyLine = false for line in rImg:gmatch("([^\n]*)\n?") do w = math.max(w,#line) h = h+1 if line == "" then emptyLine = true else emptyLine = false -- only if emptyLine is at end itll be true, very good end end if emptyLine then -- fking craftos pc man h = h-1 end end if background.resize == "stretch" then local tWin = window.create(term.current(),1,1,w,h,false) local oterm = term.current() term.redirect(tWin) term.setBackgroundColor(col) term.clear() lUtils.renderImg(rImg,1,1) term.redirect(oterm) if h/w > th/tw then -- height should overflow, width equals screen width local iw,ih=tw,math.floor(tw*(h/w)+0.5) local lWin = lUtils.littlewin(tWin,iw,ih) lWin.render(1,math.floor(th/2-ih/2)+1) else local iw,ih=math.floor(th*(w/h)+0.5),th local lWin = lUtils.littlewin(tWin,iw,ih) lWin.render(math.floor(tw/2-iw/2)+1,1) end elseif background.resize == "center" then lUtils.renderImg(rImg,math.floor(tw/2-w/2)+1,math.floor(th/2-h/2)+1,nil,true) elseif background.resize == "repeat" or true then local rw,rh = math.ceil(tw/w),math.ceil(th/h) local frame = 1 for ry=0,rh-1 do for rx=0,rw-1 do if img then lUtils.renderImg(img[frame],1+rx*w,1+ry*h,nil,true) frame = frame+1 if frame > #img then frame = 1 end else lUtils.renderImg(rImg,1+rx*w,1+ry*h,nil,true) end end end end elseif background.color then term.setBackgroundColor(background.color) term.clear() end end local selected = {} local drag local oldWidth,oldHeight = getDesktopSize() local function render(dodebug) term.redirect(terminal) -- if not position gen position -- make order table with IDs, then sort that table and iterate through local dolog if lOS.explorer.desktopBackground then local dw,dh = lOS.explorer.desktopBackground.getSize() local tw,th = term.getSize() if dh ~= th-lOS.tbSize then lOS.explorer.desktopBackground = nil else lOS.explorer.desktopBackground.setVisible(true) lOS.explorer.desktopBackground.setVisible(false) end end if not lOS.explorer.desktopBackground then local col = dConfig.background.color or colors.white local tw,th = term.getSize() th = th-lOS.tbSize local cTerm = term.current() local bWin = window.create(term.current(),1,1,tw,th,true) term.redirect(bWin) term.setBackgroundColor(col) term.clear() if dConfig.background and dConfig.background[1] and type(dConfig.background[1]) == "table" then for t=1,#dConfig.background do drawBackground(dConfig.background[t]) end else drawBackground(dConfig.background) end term.redirect(cTerm) lOS.explorer.desktopBackground = bWin lOS.explorer.desktopBackground.setVisible(false) end term.setTextColor(dConfig.textColor or colors.black) local newWidth,newHeight = getDesktopSize() if oldWidth ~= newWidth or oldHeight ~= newHeight then currentSize = newWidth..","..newHeight oldWidth = newWidth oldHeight = newHeight if not dConfig.sizes[currentSize] then dConfig.sizes[currentSize] = {} end clearDesktopMap() end local order = {} for path,id in pairs(idReference) do local absolutePath = fc("User/Desktop",path) if not fs.exists(absolutePath) then if dConfig.sizes[currentSize][id] then local self = dConfig.sizes[currentSize][id] if desktopMap[self.x] then desktopMap[self.x][self.y] = nil end dConfig.sizes[currentSize][id] = nil end idReference[path] = nil dConfig.files[id] = nil else table.insert(order,id) end end table.sort(order) local icons = dConfig.sizes[currentSize] for i=1,#order do local id = order[i] if not icons[id] then icons[id] = {} end if not icons[id].x or not icons[id].y then local x,y = 1,1 local success = true while desktopMap[x][y] do y = y+1 if y > newHeight then y = 1 x = x+1 if x > newWidth then success = false break end end end if success then icons[id].x,icons[id].y = x,y desktopMap[x][y] = id end end if icons[id].x and icons[id].y and not selected[id] then local x,y = icons[id].x,icons[id].y desktopMap[x][y] = id local path = fc("User/Desktop",dConfig.files[id]) local maxLines = 1 term.setBackgroundColor(colors.white) lOS.explorer.drawIcon(path,1+(x-1)*8,1+(y-1)*5,false,true,maxLines,{"\24","0","8"}) end --os.sleep(0.5) end for id,v in pairs(selected) do if not icons[id] then selected[id] = nil else local x,y = icons[id].x,icons[id].y local path = fc("User/Desktop",dConfig.files[id]) local maxLines = 4 term.setBackgroundColor(colors.lightBlue) lOS.explorer.drawIcon(path,1+(x-1)*8,1+(y-1)*5,false,false,maxLines,{"\24","0","8"}) end end if drag and drag.moved then lOS.explorer.drawIcon(fc("User/Desktop",dConfig.files[drag.id]),drag.x-drag.ox,drag.y-drag.oy,false,true,1,{"\24","0","8"}) end end -- CONTEXT MENU FUNCTIONS local fTypes = fileTypes local function fExec(obj) local f = obj.file --[[local num = obj.num local p = fTypes[f.type].c[2][num]] local p = obj.p if p == "Lua" then lOS.execute(f.path) else lOS.execute(p.." "..f.path) end end lOS.explorer.fExec = fExec local function fOpenWin(obj) local f = obj.file lOS.execute("Program_Files/LevelOS/Explorer "..f.path) end lOS.explorer.fOpenWin = fOpenWin function lOS.explorer.fRename(obj,s,sl,render,LevelOS,isDesktop) if type(obj) == "string" then if isDesktop then for i,v in pairs(dConfig.sizes[currentSize]) do _G.debugcompare = {} if obj == fs.combine("User/Desktop",dConfig.files[i]) then local f = genFile(obj) local x,y = v.x,v.y f.x1,f.y1 = 1+(x-1)*8,1+(y-1)*5 local lineH = math.min(#lUtils.wordwrap(lUtils.getFileName(f.path),7),4) f.x2,f.y2 = f.x1+6,f.y1+3+lineH obj = {file=f} break end table.insert(debugcompare,{obj,fs.combine("User/Desktop",dConfig.files[i])}) end if type(obj) == "string" then error("not found") end else for k,v in ipairs(sl.files) do if v.path == obj then obj = {file=v} break end end end end LevelOS.overlay = nil local f = obj.file sl.renaming = f.path if isDesktop then term.setBackgroundColor(colors.white) term.setTextColor(colors.black) else term.setBackgroundColor(colors.pink) opink = {s.win.getPaletteColor(colors.pink)} sl.opink = opink s.win.setPaletteColor(colors.pink,0.15,0.15,0.15) term.setTextColor(colors.white) end local fname local isShortcut = false if lUtils.getFileType(f.path) == ".llnk" then fname = lUtils.getFileName(f.path,false) isShortcut = true else fname = lUtils.getFileName(f.path,true) end fname = fname:gsub(" ","_") local w,h = term.getSize() if sl.rMode == 1 then sl.renamebox = lUtils.input(sl.NAME.x+2,f.y2,sl.NAME.x+sl.NAME.width-2,f.y2,{overflowX="scroll",overflowY="none",text=fname,selectColor=colors.blue}) sl.renamebox.x2 = math.min(math.max(sl.NAME.width,#sl.renamebox.txt+5),w) else sl.renamebox = lUtils.input(f.x1,f.y1+4,f.x2,f.y2,{overflowX="scroll",overflowY="none",text=fname,selectColor=colors.blue}) -- ah fuck ah FCK shit fuck if isDesktop then sl.renamebox.opt.selectTxtColor = colors.white end -- put renamebox in sl or something i guess FUCK why did i make it this way end local renamebox = sl.renamebox renamebox.isShortcut = isShortcut renamebox.scrollX = 0 renamebox.state = true local ext = lUtils.getFileType(f.path) if ext == ".llnk" then ext = "" end renamebox.select = {1,#fname-#ext} renamebox.cursor.a = 1+#fname-#ext renamebox.cursor.x = renamebox.cursor.a renamebox.update("timer") local ok,err = pcall(function() render(true) end) if not ok then lOS.bsod(err) end renamebox.render() os.queueEvent("renamebox") end local function fInvShort(obj,updateFiles,render) local o = {lUtils.popup("Problem with shortcut","The item '"..obj.file.sName.."' that this shortcut refers to has been changed or moved, so this shortcut will no longer work properly.\n\nDo you want to delete this shortcut?",37,13,{"Yes","No"})} if o[1] and o[3] == "Yes" then fs.delete(obj.file.path) updateFiles() end term.setTextColor(colors.white) render() end lOS.explorer.fInvShort = fInvShort local function genContextMenu(f,s,sl,selected,updateFiles,render,LevelOS,isDesktop) local shortcache = lOS.explorer.shortcache local winObj = term.current() local function fInvShortInternal(obj) term.redirect(winObj) LevelOS.overlay = nil lOS.noEvents = false LevelOS.self.window.events = nil fInvShort(obj,updateFiles,render) term.setTextColor(colors.white) end local function fDelete(obj) for k,v in pairs(selected) do fs.delete(k) end selected = {} updateFiles() end local function fOpen(obj) local f = obj.file selected = {} sl.folder = f.path updateFiles() scrollY = 0 end local function fCut(obj) lOS.fClipboard = {} for k,v in pairs(selected) do table.insert(lOS.fClipboard,k) end lOS.fCut = lUtils.instantiate(lOS.fClipboard) selected = {} end local function fCopy(obj) lOS.fClipboard = {} lOS.fCut = {} for k,v in pairs(selected) do table.insert(lOS.fClipboard,k) end end local function fPaste(obj) local tFolder = sl.folder for c=1,#lOS.fClipboard do if fs.exists(lOS.fClipboard[c]) == true then fs.copy(lOS.fClipboard[c],uFP(fs.combine(tFolder,fs.getName(lOS.fClipboard[c])))) end if locateEntry(lOS.fCut,lOS.fClipboard[c]) == true then fs.delete(lOS.fClipboard[c]) table.remove(lOS.fCut,({locateEntry(lOS.fCut,lOS.fClipboard[c])})[2]) end end lOS.fClipboard = {} lOS.fCut = {} updateFiles() end local opink local function fRename(obj) lOS.explorer.fRename(obj,s,sl,render,LevelOS,isDesktop) if isDesktop then local renamebox = sl.renamebox term.redirect(terminal) render() renamebox.render() lOS.noEvents = false while true do local e = {os.pullEventRaw()} if e[1] == "char" and e[2] == " " then e[2] = "_" end if e[1] == "key" and e[2] == keys.enter then renamebox.state = false --sl.renaming = nil else renamebox.update(unpack(e)) --render() renamebox.render() end if not renamebox.state then local pth = fs.combine("User/Desktop",renamebox.txt) if renamebox.isShortcut then pth = pth..".llnk" end if pth == sl.renaming or fs.combine(pth,"") == "User/Desktop" then -- nothing elseif fs.exists(pth) then local newPth = uFP(pth) local r = {lUtils.popup("Rename File","Do you want to rename \""..fs.getName(sl.renaming):gsub("_"," ").."\" to \""..fs.getName(newPth):gsub("_"," ").."\"?\n\nThere is already a file with the same name in this location.",41,11,{"Yes","No"})} if r[1] and r[3] == "Yes" then fs.move(sl.renaming,newPth) end else fs.move(sl.renaming,pth) end renamebox = nil sl.renamebox = nil sl.renaming = nil term.setCursorBlink(false) updateFiles() render() break end end end end local function fNew(obj) local pth = uFP(fs.combine(sl.folder,"New_"..obj.txt:gsub(" ","_").."."..obj.format)) lUtils.fwrite(pth,obj.preset) term.redirect(winObj) updateFiles() render() fRename(pth) -- rename end local function fNewFolder(obj) local pth = uFP(fs.combine(sl.folder,"New_Folder")) fs.makeDir(pth) term.redirect(winObj) updateFiles() render() fRename(pth) -- rename end local function fOpenWith(obj) if LevelOS and LevelOS.self and LevelOS.self.window then LevelOS.self.window.events = nil end LevelOS.overlay = nil lOS.noEvents = false local p = sl.openWith(obj.file) if p then p = p.path local f = obj.file if p == "Lua" then lOS.execute(f.path) else lOS.execute(p.." "..f.path) end end end local function fPin(obj) table.insert(sl.config.quickaccess,obj.file.path) sl.saveConfig() sl.reloadQuickAccess() end local function fUnpin(obj) local s,i = locateEntry(sl.config.quickaccess,obj.file.path) if s then table.remove(sl.config.quickaccess,i) sl.saveConfig() sl.reloadQuickAccess() end end local function fShortcut(obj) local pth = uFP(fs.combine(obj.folder,obj.name:gsub(" ","_").."_-_Shortcut.llnk")) lUtils.asset.save({obj.file.path},pth) updateFiles() render() end local function fDesktopShortcut(obj) lOS.genIco(obj.file.path) --[[local pth = uFP(fs.combine(obj.folder,obj.name:gsub(" ","_")..".llnk")) lUtils.asset.save({obj.file.path},pth) os.queueEvent("explorer_reload")]] end local function fBackground(obj) lOS.explorer.desktopConfig.background = {path=obj.file.path,resize=obj.txt:lower()} os.queueEvent("explorer_reload") end local function fAddToBackground(obj) local dConfig = lOS.explorer.desktopConfig if not dConfig.background[1] then local obg = dConfig.background dConfig.background = {color=obg.color,obg} end table.insert(dConfig.background,{path=obj.file.path,resize=obj.txt:lower()}) os.queueEvent("explorer_reload") lOS.explorer.desktopBackground = nil end local function fCopyPath(obj) ccemux.setClipboard(obj.file.path) end if isDesktop then fOpen = fOpenWin end local options if not f then local newfiles = {} for k,v in pairs(fTypes) do if type(v) == "table" and type(v.emptyFilePreset) == "string" then table.insert(newfiles,{txt=v.name,preset=v.emptyFilePreset,action=fNew,format=k}) end end table.insert(newfiles,{txt="bImg Icon",preset='{{{" "," "," "},{" "," "," "},{" "," "," "}}}',action=fNew,format="bimg"}) local opt = { {{txt="Refresh",action=updateFiles}}, {{txt="Paste",action=fPaste,disabled=(#lOS.fClipboard == 0 or fs.isReadOnly(sl.folder))}}, {{txt="New",disabled=(fs.isReadOnly(sl.folder)),action={{txt="Folder",action=fNewFolder},newfiles}}} -- import from formats.lconf } if isDesktop then local txtcolors = {} for k,v in pairs(colors) do if type(v) == "number" then table.insert(txtcolors,k) end end table.sort(txtcolors) local txtcoloroptions = {} for c=1,#txtcolors do local col = colors[txtcolors[c]] local name = txtcolors[c]:sub(1,1):upper()..txtcolors[c]:sub(2) local b = lUtils.toBlit(col) if dConfig.textColor == col then table.insert(txtcoloroptions,{txt={" \7 "..name,nil,string.rep(b,3)}}) if col == colors.white then txtcoloroptions[#txtcoloroptions].txt[2] = "fff" end else table.insert(txtcoloroptions,{txt={" "..name,nil,string.rep(b,3)},action=function() dConfig.textColor = col updateFiles() render() end}) end end if not dConfig.textColor then table.insert(txtcoloroptions,1,{txt=" \7 Automatic"}) else table.insert(txtcoloroptions,1,{txt=" Automatic",action=function() dConfig.textColor = nil updateFiles() render() end}) end table.insert(opt[1],1,{txt="View",action={ {txt="Text color",action={txtcoloroptions}} }}) end if ccemux then table.insert(opt,{{txt="Open External Explorer",action=function() ccemux.openDataDir() end}}) end options = opt else if type(f) == "string" then f = genFile(f) end local file = f.path local nf = f local invalidShort if shortcache[file] then f.sPath = shortcache[file][1] f.sName = fs.getName(f.sPath) if fs.exists(f.sPath) then nf = genFile(f.sPath) else invalidShort = true end end options = { { }, { {txt="Cut",action=fCut}, {txt="Copy",action=fCopy} }, { {txt="Delete",action=fDelete}, {txt="Rename",action=fRename,file=f,sl=sl} } } local createshortcut = {txt="Create shortcut",file=nf,folder=sl.folder,name=nf.name,action=fShortcut} local createshortcut2 = {txt="Create shortcut on desktop",file=nf,folder="User/Desktop",name=nf.name,action=fDesktopShortcut} if fs.getName(nf.path) == "main.lua" then createshortcut.name = fs.getName(fs.getDir(nf.path)) createshortcut2.name = fs.getName(fs.getDir(nf.path)) end if invalidShort then createshortcut.action = fInvShortInternal createshortcut2.action = fInvShortInternal end if not isDesktop then table.insert(options[3],1,createshortcut2) table.insert(options[3],1,createshortcut) end local disabled = {} if f.readOnly == true then disabled = {Edit=true,Cut=true,Delete=true,Rename=true} elseif disks[file] ~= nil then disabled = {Edit=true,Cut=true,Delete=true,Rename=true} disabled["Create Shortcut"] = true end local fc = fs.combine if ccemux then table.insert(options[3],{txt="Copy path",file=f,action=fCopyPath}) end local fOpen = fOpen local fOpenWin = fOpenWin local fOpenWith = fOpenWith local fExec = fExec local fUnpin = fUnpin local fPin = fPin if invalidShort then fOpen = fInvShortInternal fOpenWin = fInvShortInternal fOpenWith = fInvShortInternal fExec = fInvShortInternal fUnpin = fInvShortInternal fPin = fInvShortInternal end if nf.isDir then local etxt = "" local isProgram = false if fs.exists(fc(nf.path,"main.lua")) then isProgram = true etxt = "folder " end options[1] = {{txt="Open "..etxt,action=fOpen,file=nf}} if not isDesktop then table.insert(options[1],{txt="Open "..etxt.."in new window",action=fOpenWin,file=nf}) end if isProgram then table.insert(options[1],{txt="Execute",action=fExec,p="Lua",file=nf}) createshortcut.action = {{txt="To program",file=genFile(fc(nf.path,"main.lua")),folder=sl.folder,name=nf.name,action=fShortcut},{txt="To folder",file=nf,folder=sl.folder,name=nf.name,action=fShortcut}} end if not isDesktop then if locateEntry(sl.config.quickaccess,nf.path) then table.insert(options[1],{txt="Unpin from Quick access",action=fUnpin,file=nf}) else table.insert(options[1],{txt="Pin to Quick access",action=fPin,file=nf}) end end elseif fTypes[nf.type] and fTypes[nf.type].contextMenu and not invalidShort then local tbl = {} for k,v in ipairs(fTypes[nf.type].contextMenu[1]) do table.insert(tbl,{txt=v,file=nf,p=fTypes[nf.type].contextMenu[2][k],action=fExec}) end if nf.type == "bimg" or nf.type == "limg" or nf.type == "nfp" then table.insert(tbl,{txt="Set as desktop background",action={{{txt="Stretch",file=nf,action=fBackground},{txt="Repeat",file=nf,action=fBackground},{txt="Center",file=nf,action=fBackground}}}}) table.insert(tbl,{txt="Add to desktop background",action={{{txt="Repeat",file=nf,action=fAddToBackground},{txt="Center",file=nf,action=fAddToBackground}}},disabled=(not lOS.explorer.desktopConfig.background)}) end options[1] = tbl else options[1] = {{txt="Edit",action=fExec,p="rom/programs/edit.lua",file=nf}} end if shortcache[file] then if invalidShort then table.insert(options[1],2,{txt="Open file location",disabled=true}) else table.insert(options[1],2,{txt="Open file location",action=fOpen,file=genFile(fs.getDir(nf.path))}) end end local ow if fTypes[nf.type] and fTypes[nf.type].openWith and not nf.isDir then local owtbl = {} for k,v in ipairs(fTypes[nf.type].openWith) do table.insert(owtbl,{txt=lUtils.getFileName(v),file=nf,p=v,action=fExec}) end ow = {txt="Open with",action={owtbl,{txt="Choose another app",action=fOpenWith,file=nf,disabled=isDesktop}}} if invalidShort then ow.disabled = true end table.insert(options[1],ow) end if nf.readOnly == true --[[and locateEntry(options[1],"Edit") == true]] then for k,v in ipairs(options[1]) do if type(v) == "table" and v.txt == "Edit" then v.txt = "View" end end --options[1][({locateEntry(options[1],"Edit")})[2]] = "View" end for _,cat in ipairs(options) do for k,v in ipairs(cat) do if type(v) == "string" and disabled[v] then cat[k] = {txt=v,disabled=true} elseif type(v) == "table" and disabled[v.txt] then v.disabled = true end end end end return options end lOS.explorer.genContextMenu = genContextMenu local function cMenu(f, x, y) local sel = {} for k,v in pairs(selected) do local path = fc("User/Desktop",dConfig.files[k]) sel[path] = true end local options = genContextMenu(f,{win=term.current()},{folder="User/Desktop"},sel,reloadDesktop,render,LevelOS,true) local output = {lOS.contextmenu(x,y,30,options,nil,true)} return unpack(output) end render() os.sleep(0.05) render() local lastUpdate = os.epoch("utc") local tID = os.startTimer(10) while true do local e = {os.pullEvent()} if e[1] == "explorer_full_reload" then lOS.explorer.shortcache = {} lOS.explorer.imgcache = {} lOS.explorer.nimgcache = {} lOS.explorer.desktopBackground = nil reloadDesktop() render() elseif e[1] == "term_resize" or e[1] == "explorer_reload" then lOS.explorer.desktopBackground = nil reloadDesktop() render() elseif e[1]:find("mouse") and e[3] and e[4] then local x,y = math.ceil(e[3]/8),math.ceil(e[4]/5) if e[1] == "mouse_click" then lOS.focusWin = lOS.wins[0] end if e[1] == "mouse_drag" and drag then drag.x,drag.y = e[3],e[4] drag.moved = true render() elseif e[1] == "mouse_up" and drag then if not desktopMap[x][y] then desktopMap[x][y] = drag.id local icon = dConfig.sizes[currentSize][drag.id] desktopMap[icon.x][icon.y] = nil icon.x,icon.y = x,y lUtils.asset.save(dConfig,"LevelOS/data/desktop.lconf") end drag = nil render() elseif e[3]%8 ~= 0 and desktopMap[x][y] then if e[1] == "mouse_click" then local id = desktopMap[x][y] if selected[id] and os.epoch("utc") < selected[id]+500 and e[2] == 1 then local path = fc("User/Desktop",dConfig.files[id]) local rPath = path local cmd = path local shortcache = lOS.explorer.shortcache local exec = false local invalidShort = false local f = genFile(path) if shortcache[path] then cmd = shortcache[path][1] rPath = cmd f.sName = rPath if not fs.exists(rPath) then invalidShort = true end if shortcache[path].args and #shortcache[path].args > 0 then cmd = cmd.." "..table.concat(shortcache[path].args) end if shortcache[path].program then if shortcache[path].program ~= "Lua" then cmd = shortcache[path].program.." "..cmd end exec = true end end if invalidShort then fInvShort({file=f},reloadDesktop,render) else local fType = lUtils.getFileType(rPath):sub(2) if exec then lOS.execute(cmd) elseif fs.isDir(rPath) then lOS.execute("Program_Files/LevelOS/Explorer "..cmd) elseif fileTypes[fType] and fileTypes[fType].program then local p = fileTypes[fType].program if p == "Lua" then lOS.execute(cmd) else lOS.execute(p.." "..cmd) end elseif fType == "" then lOS.execute(cmd) end end selected = {} else if not (lUtils.isHolding(keys.leftCtrl) or lUtils.isHolding(keys.leftShift)) then selected = {} end if e[2] == 1 then selected[id] = os.epoch("utc") drag = {id=id,ox=(e[3]-1)%8,oy=(e[4]-1)%5,x=e[3],y=e[4],moved=false} else selected[id] = 0 end end render() elseif e[1] == "mouse_up" and e[2] == 2 then local id = desktopMap[x][y] local path = fc("User/Desktop",dConfig.files[id]) --[[local rPath = path local cmd = path local shortcache = lOS.explorer.shortcache local exec = false]] local f = genFile(path) f.x1,f.y1 = 1+(x-1)*8,1+(y-1)*5 local lineH = math.min(#lUtils.wordwrap(lUtils.getFileName(f.path),7),4) f.x2,f.y2 = f.x1+6,f.y1+3+lineH cMenu(f,e[3],e[4]) end elseif e[1] == "mouse_click" and not (lUtils.isHolding(keys.leftCtrl) or lUtils.isHolding(keys.leftShift)) then selected = {} render() if e[2] == 2 then cMenu(nil, e[3], e[4]) end end elseif (e[1] == "timer" and e[2] == tID) or os.epoch("utc")-10000 > lastUpdate then lastUpdate = os.epoch("utc") if not (e[1] == "timer" and e[2] == tID) then os.cancelTimer(tID) end tID = os.startTimer(10) reloadDesktop() render() end if e[1] == "mouse_up" then drag = nil end end