From 4e6e93596b5619be15dff8e7ece0178e09d20161 Mon Sep 17 00:00:00 2001 From: Igor Timofeev Date: Sun, 6 Sep 2015 17:05:05 +0300 Subject: [PATCH] Update OS.lua --- MineOS/OS.lua | 3026 +++++++++++++++++-------------------------------- 1 file changed, 1036 insertions(+), 1990 deletions(-) diff --git a/MineOS/OS.lua b/MineOS/OS.lua index 51cd1289..2f7bcc5d 100644 --- a/MineOS/OS.lua +++ b/MineOS/OS.lua @@ -1,2001 +1,1047 @@ -local component = require("component") -local term = require("term") -local unicode = require("unicode") -local event = require("event") -local fs = require("filesystem") -local shell = require("shell") -local keyboard = require("keyboard") -local computer = require("computer") -local fs = require("filesystem") ---local thread = require("thread") -local gpu = component.gpu -local screen = component.screen -local ECSAPI = {} - ----------------------------------------------------------------------------------------------------- - -ECSAPI.windowColors = { - background = 0xeeeeee, - usualText = 0x444444, - subText = 0x888888, - tab = 0xaaaaaa, - title = 0xffffff, - shadow = 0x444444, -} - -ECSAPI.colors = { - white = 0xF0F0F0, - orange = 0xF2B233, - magenta = 0xE57FD8, - lightBlue = 0x99B2F2, - yellow = 0xDEDE6C, - lime = 0x7FCC19, - pink = 0xF2B2CC, - gray = 0x4C4C4C, - lightGray = 0x999999, - cyan = 0x4C99B2, - purple = 0xB266E5, - blue = 0x3366CC, - brown = 0x7F664C, - green = 0x57A64E, - red = 0xCC4C4C, - black = 0x000000 -} - ----------------------------------------------------------------------------------------------------- - ---МАСШТАБ МОНИТОРА -function ECSAPI.setScale(scale, debug) - --КОРРЕКЦИЯ МАСШТАБА, ЧТОБЫ ВСЯКИЕ ДАУНЫ НЕ ДЕЛАЛИ ТОГО, ЧЕГО НЕ СЛЕДУЕТ - if scale > 1 then - scale = 1 - elseif scale < 0.1 then - scale = 0.1 - end - - --Просчет пикселей в блоках кароч - забей, так надо - local function calculateAspect(screens) - local abc = 12 - - if screens == 2 then - abc = 28 - elseif screens > 2 then - abc = 28 + (screens - 2) * 16 - end - - return abc - end - - --Собсна, арсчет масштаба - local xScreens, yScreens = component.screen.getAspectRatio() - - local xPixels, yPixels = calculateAspect(xScreens), calculateAspect(yScreens) - - local proportion = xPixels / yPixels - - --Костыль - local xMax, yMax = gpu.maxResolution() - xMax = yMax * 2 - - local newWidth, newHeight - - if proportion >= 1 then - newWidth = math.floor(xMax * scale) - newHeight = math.floor(newWidth / proportion / 2) - else - newHeight = math.floor(yMax * scale) - newWidth = math.floor(newHeight * proportion * 2) - end - - if debug then - print(" ") - print("Максимальное разрешение: "..xMax.."x"..yMax) - print("Пропорция монитора: "..xPixels.."x"..yPixels) - print(" ") - print("Новое разрешение: "..newWidth.."x"..newHeight) - print(" ") - end - - gpu.setResolution(newWidth, newHeight) -end - ---Сделать строку пригодной для отображения в ОпенКомпах -function ECSAPI.stringOptimize(sto4ka, indentatonWidth) - indentatonWidth = indentatonWidth or 2 - sto4ka = string.gsub(sto4ka, "\r\n", "\n") - sto4ka = string.gsub(sto4ka, " ", string.rep(" ", indentatonWidth)) - return stro4ka -end - ---ИЗ ДЕСЯТИЧНОЙ В ШЕСТНАДЦАТИРИЧНУЮ -function ECSAPI.decToBase(IN,BASE) - local hexCode = "0123456789ABCDEFGHIJKLMNOPQRSTUVW" - OUT = "" - local ostatok = 0 - while IN>0 do - ostatok = math.fmod(IN,BASE) + 1 - IN = math.floor(IN/BASE) - OUT = string.sub(hexCode,ostatok,ostatok)..OUT - end - if #OUT == 1 then OUT = "0"..OUT end - if OUT == "" then OUT = "00" end - return OUT -end - ---ИЗ 16 В РГБ -function ECSAPI.HEXtoRGB(color) - color = math.ceil(color) - - local rr = bit32.rshift( color, 16 ) - local gg = bit32.rshift( bit32.band(color, 0x00ff00), 8 ) - local bb = bit32.band(color, 0x0000ff) - - return rr, gg, bb -end - ---ИЗ РГБ В 16 -function ECSAPI.RGBtoHEX(rr, gg, bb) - return bit32.lshift(rr, 16) + bit32.lshift(gg, 8) + bb -end - ---ИЗ ХСБ В РГБ -function ECSAPI.HSBtoRGB(h, s, v) - local rr, gg, bb = 0, 0, 0 - local const = 255 - - s = s/100 - v = v/100 - - local i = math.floor(h/60) - local f = h/60 - i - - local p = v*(1-s) - local q = v*(1-s*f) - local t = v*(1-(1-f)*s) - - if ( i == 0 ) then rr, gg, bb = v, t, p end - if ( i == 1 ) then rr, gg, bb = q, v, p end - if ( i == 2 ) then rr, gg, bb = p, v, t end - if ( i == 3 ) then rr, gg, bb = p, q, v end - if ( i == 4 ) then rr, gg, bb = t, p, v end - if ( i == 5 ) then rr, gg, bb = v, p, q end - - return rr*const, gg*const, bb*const -end - ---КЛИКНУЛИ ЛИ В ЗОНУ -function ECSAPI.clickedAtArea(x,y,sx,sy,ex,ey) - if (x >= sx) and (x <= ex) and (y >= sy) and (y <= ey) then return true end - return false -end - ---ОЧИСТКА ЭКРАНА ЦВЕТОМ -function ECSAPI.clearScreen(color) - if color then gpu.setBackground(color) end - term.clear() -end - ---ПРОСТОЙ СЕТПИКСЕЛЬ, ИБО ЗАЕБАЛО -function ECSAPI.setPixel(x,y,color) - gpu.setBackground(color) - gpu.set(x,y," ") -end - ---ЦВЕТНОЙ ТЕКСТ -function ECSAPI.colorText(x,y,textColor,text) - gpu.setForeground(textColor) - gpu.set(x,y,text) -end - ---ЦВЕТНОЙ ТЕКСТ С ЖОПКОЙ! -function ECSAPI.colorTextWithBack(x,y,textColor,backColor,text) - gpu.setForeground(textColor) - gpu.setBackground(backColor) - gpu.set(x,y,text) -end - ---ИНВЕРСИЯ HEX-ЦВЕТА -function ECSAPI.invertColor(color) - return 0xffffff - color -end - ---АДАПТИВНЫЙ ТЕКСТ, ПОДСТРАИВАЮЩИЙСЯ ПОД ФОН -function ECSAPI.adaptiveText(x,y,text,textColor) - gpu.setForeground(textColor) - x = x - 1 - for i=1,unicode.len(text) do - local info = {gpu.get(x+i,y)} - gpu.setBackground(info[3]) - gpu.set(x+i,y,unicode.sub(text,i,i)) - end -end - ---ИНВЕРТИРОВАННЫЙ ПО ЦВЕТУ ТЕКСТ НА ОСНОВЕ ФОНА -function ECSAPI.invertedText(x,y,symbol) - local info = {gpu.get(x,y)} - ECSAPI.adaptiveText(x,y,symbol,ECSAPI.invertColor(info[3])) -end - ---АДАПТИВНОЕ ОКРУГЛЕНИЕ ЧИСЛА -function ECSAPI.adaptiveRound(chislo) - local celaya,drobnaya = math.modf(chislo) - if drobnaya >= 0.5 then - return (celaya + 1) - else - return celaya - end -end - ---Округление до опред. кол-ва знаков после запятой -function ECSAPI.round(num, idp) - local mult = 10^(idp or 0) - return math.floor(num * mult + 0.5) / mult -end - -function ECSAPI.square(x,y,width,height,color) - gpu.setBackground(color) - gpu.fill(x,y,width,height," ") -end - -function ECSAPI.border(x, y, width, height, back, fore) - local stringUp = "┌"..string.rep("─", width - 2).."┐" - local stringDown = "└"..string.rep("─", width - 2).."┘" - gpu.setForeground(fore) - gpu.setBackground(back) - gpu.set(x, y, stringUp) - gpu.set(x, y + height - 1, stringDown) - - local yPos = 1 - for i = 1, (height - 2) do - gpu.set(x, y + yPos, "│") - gpu.set(x + width - 1, y + yPos, "│") - yPos = yPos + 1 - end -end - -function ECSAPI.separator(x, y, width, back, fore) - ECSAPI.colorTextWithBack(x, y, fore, back, string.rep("─", width)) -end - ---АВТОМАТИЧЕСКОЕ ЦЕНТРИРОВАНИЕ ТЕКСТА ПО КООРДИНАТЕ -function ECSAPI.centerText(mode,coord,text) - local dlina = unicode.len(text) - local xSize,ySize = gpu.getResolution() - - if mode == "x" then - gpu.set(math.floor(xSize/2-dlina/2),coord,text) - elseif mode == "y" then - gpu.set(coord,math.floor(ySize/2),text) - else - gpu.set(math.floor(xSize/2-dlina/2),math.floor(ySize/2),text) - end -end - --- -function ECSAPI.drawCustomImage(x,y,pixels) - x = x - 1 - y = y - 1 - local pixelsWidth = #pixels[1] - local pixelsHeight = #pixels - local xEnd = x + pixelsWidth - local yEnd = y + pixelsHeight - - for i=1,pixelsHeight do - for j=1,pixelsWidth do - if pixels[i][j][3] ~= "#" then - gpu.setBackground(pixels[i][j][1]) - gpu.setForeground(pixels[i][j][2]) - gpu.set(x+j,y+i,pixels[i][j][3]) - end - end - end - - return (x+1),(y+1),xEnd,yEnd -end - ---КОРРЕКТИРОВКА СТАРТОВЫХ КООРДИНАТ -function ECSAPI.correctStartCoords(xStart,yStart,xWindowSize,yWindowSize) - local xSize,ySize = gpu.getResolution() - if xStart == "auto" then - xStart = math.floor(xSize/2 - xWindowSize/2) - end - if yStart == "auto" then - yStart = math.floor(ySize/2 - yWindowSize/2) - end - return xStart,yStart -end - ---ЗАПОМНИТЬ ОБЛАСТЬ ПИКСЕЛЕЙ -function ECSAPI.rememberOldPixels(x, y, x2, y2) - local newPNGMassiv = { ["backgrounds"] = {} } - newPNGMassiv.x, newPNGMassiv.y = x, y - - --Перебираем весь массив стандартного PNG-вида по высоте - local xCounter, yCounter = 1, 1 - for j = y, y2 do - xCounter = 1 - for i = x, x2 do - local symbol, fore, back = gpu.get(i, j) - - newPNGMassiv["backgrounds"][back] = newPNGMassiv["backgrounds"][back] or {} - newPNGMassiv["backgrounds"][back][fore] = newPNGMassiv["backgrounds"][back][fore] or {} - - table.insert(newPNGMassiv["backgrounds"][back][fore], {xCounter, yCounter, symbol} ) - - xCounter = xCounter + 1 - back, fore, symbol = nil, nil, nil - end - - yCounter = yCounter + 1 - end - - return newPNGMassiv -end - ---НАРИСОВАТЬ ЗАПОМНЕННЫЕ ПИКСЕЛИ ИЗ МАССИВА -function ECSAPI.drawOldPixels(massivSudaPihay) - - --Отнимаем разок - --massivSudaPihay.x, massivSudaPihay.y = massivSudaPihay.x - 1, massivSudaPihay.y - 1 - - --Перебираем массив с фонами - for back, backValue in pairs(massivSudaPihay["backgrounds"]) do - gpu.setBackground(back) - for fore, foreValue in pairs(massivSudaPihay["backgrounds"][back]) do - gpu.setForeground(fore) - for pixel = 1, #massivSudaPihay["backgrounds"][back][fore] do - if massivSudaPihay["backgrounds"][back][fore][pixel][3] ~= transparentSymbol then - gpu.set(massivSudaPihay.x + massivSudaPihay["backgrounds"][back][fore][pixel][1] - 1, massivSudaPihay.y + massivSudaPihay["backgrounds"][back][fore][pixel][2] - 1, massivSudaPihay["backgrounds"][back][fore][pixel][3]) - end - end - end - end -end - ---ОГРАНИЧЕНИЕ ДЛИНЫ СТРОКИ -function ECSAPI.stringLimit(mode, text, size, noDots) - if unicode.len(text) <= size then return text end - local length = unicode.len(text) - if mode == "start" then - if noDots then - return unicode.sub(text, length - size + 1, -1) - else - return "…" .. unicode.sub(text, length - size + 2, -1) - end - else - if noDots then - return unicode.sub(text, 1, size) - else - return unicode.sub(text, 1, size - 1) .. "…" - end - end -end - ---ПОЛУЧИТЬ СПИСОК ФАЙЛОВ ИЗ КОНКРЕТНОЙ ДИРЕКТОРИИ -function ECSAPI.getFileList(path) - local list = fs.list(path) - local massiv = {} - for file in list do - --if string.find(file, "%/$") then file = unicode.sub(file, 1, -2) end - table.insert(massiv, file) - end - list = nil - return massiv -end - ---ПОЛУЧИТЬ ВСЕ ДРЕВО ФАЙЛОВ -function ECSAPI.getFileTree(path) - local massiv = {} - local list = ECSAPI.getFileList(path) - for key, file in pairs(list) do - if fs.isDirectory(path.."/"..file) then - table.insert(massiv, getFileTree(path.."/"..file)) - else - table.insert(massiv, file) - end - end - list = nil - - return massiv -end - ---ПОЛУЧЕНИЕ ФОРМАТА ФАЙЛА -function ECSAPI.getFileFormat(path) - local name = fs.name(path) - local starting, ending = string.find(name, "(.)%.[%d%w]*$") - if starting == nil then - return nil - else - return unicode.sub(name,starting + 1, -1) - end - name, starting, ending = nil, nil, nil -end - ---ПРОВЕРКА, СКРЫТЫЙ ЛИ ФАЙЛ -function ECSAPI.isFileHidden(path) - local name = fs.name(path) - local starting, ending = string.find(name, "^%.(.*)$") - if starting == nil then - return false - else - return true - end - name, starting, ending = nil, nil, nil -end - ---СКРЫТЬ РАСШИРЕНИЕ ФАЙЛА -function ECSAPI.hideFileFormat(path) - local name = fs.name(path) - local fileFormat = ECSAPI.getFileFormat(name) - if fileFormat == nil then - return name - else - return unicode.sub(name, 1, unicode.len(name) - unicode.len(fileFormat)) - end -end - -function ECSAPI.reorganizeFilesAndFolders(massivSudaPihay, showHiddenFiles) - showHiddenFiles = showHiddenFiles or true - local massiv = {} - for i = 1, #massivSudaPihay do - if ECSAPI.isFileHidden(massivSudaPihay[i]) then - table.insert(massiv, massivSudaPihay[i]) - end - end - for i = 1, #massivSudaPihay do - local cyka = massivSudaPihay[i] - if fs.isDirectory(cyka) and not ECSAPI.isFileHidden(cyka) and ECSAPI.getFileFormat(massivSudaPihay[i]) ~= ".app" then - table.insert(massiv, massivSudaPihay[i]) - end - cyka = nil - end - for i = 1, #massivSudaPihay do - local cyka = massivSudaPihay[i] - if (not fs.isDirectory(cyka) and not ECSAPI.isFileHidden(cyka)) or (fs.isDirectory(cyka) and not ECSAPI.isFileHidden(cyka) and ECSAPI.getFileFormat(massivSudaPihay[i]) == ".app") then - table.insert(massiv, massivSudaPihay[i]) - end - cyka = nil - end - - return massiv -end - ---Бесполезна теперь, используй string.gsub() -function ECSAPI.stringReplace(stroka, chto, nachto) - local searchFrom = 1 - while true do - local starting, ending = string.find(stroka, chto, searchFrom) - if starting then - stroka = unicode.sub(stroka, 1, starting - 1) .. nachto .. unicode.sub(stroka, ending + 1, -1) - searchFrom = ending + unicode.len(nachto) + 1 - else - break - end - end - - return stroka -end - ---Ожидание клика либо нажатия какой-либо клавиши -function ECSAPI.waitForTouchOrClick() - while true do - local e = {event.pull()} - if e[1] == "key_down" or e[1] == "touch" then break end - end -end - -----------------------------ОКОШЕЧКИ, СУКА-------------------------------------------------- - ---ECSAPI.windows = {} - -function ECSAPI.drawButton(x,y,width,height,text,backColor,textColor) - x,y = ECSAPI.correctStartCoords(x,y,width,height) - - local textPosX = math.floor(x + width / 2 - unicode.len(text) / 2) - local textPosY = math.floor(y + height / 2) - ECSAPI.square(x,y,width,height,backColor) - ECSAPI.colorText(textPosX,textPosY,textColor,text) - - return x, y, (x + width - 1), (y + height - 1) -end - -function ECSAPI.drawAdaptiveButton(x,y,offsetX,offsetY,text,backColor,textColor) - local length = unicode.len(text) - local width = offsetX*2 + length - local height = offsetY*2 + 1 - - x,y = ECSAPI.correctStartCoords(x,y,width,height) - - ECSAPI.square(x,y,width,height,backColor) - ECSAPI.colorText(x+offsetX,y+offsetY,textColor,text) - - return x,y,(x+width-1),(y+height-1) -end - -function ECSAPI.windowShadow(x,y,width,height) - gpu.setBackground(ECSAPI.windowColors.shadow) - gpu.fill(x+width,y+1,2,height," ") - gpu.fill(x+1,y+height,width,1," ") -end - ---Просто белое окошко безо всего -function ECSAPI.blankWindow(x,y,width,height) - local oldPixels = ECSAPI.rememberOldPixels(x,y,x+width+1,y+height) - - ECSAPI.square(x,y,width,height,ECSAPI.windowColors.background) - - ECSAPI.windowShadow(x,y,width,height) - - return oldPixels -end - -function ECSAPI.emptyWindow(x,y,width,height,title) - - local oldPixels = ECSAPI.rememberOldPixels(x,y,x+width+1,y+height) - - --ОКНО - gpu.setBackground(ECSAPI.windowColors.background) - gpu.fill(x,y+1,width,height-1," ") - - --ТАБ СВЕРХУ - gpu.setBackground(ECSAPI.windowColors.tab) - gpu.fill(x,y,width,1," ") - - --ТИТЛ - gpu.setForeground(ECSAPI.windowColors.title) - local textPosX = x + math.floor(width/2-unicode.len(title)/2) -1 - gpu.set(textPosX,y,title) - - --ТЕНЬ - ECSAPI.windowShadow(x,y,width,height) - - return oldPixels - -end - -function ECSAPI.error(...) - - local arg = {...} - local text = arg[1] or "С твоим компом опять хуйня" - local buttonText = arg[2] or "ОК" - local sText = unicode.len(text) - local xSize, ySize = gpu.getResolution() - local width = math.ceil(xSize * 3 / 5) - if (width - 11) > (sText) then width = 11 + sText end - local textLimit = width - 11 - - --Восклицательный знак - local image = { - {{0xff0000,0xffffff,"#"},{0xff0000,0xffffff,"#"},{0xff0000,0xffffff," "},{0xff0000,0xffffff,"#"},{0xff0000,0xffffff,"#"}}, - {{0xff0000,0xffffff,"#"},{0xff0000,0xffffff," "},{0xff0000,0xffffff,"!"},{0xff0000,0xffffff," "},{0xff0000,0xffffff,"#"}}, - {{0xff0000,0xffffff," "},{0xff0000,0xffffff," "},{0xff0000,0xffffff," "},{0xff0000,0xffffff," "},{0xff0000,0xffffff," "}} - } - - --Парсинг строки ошибки - local parsedErr = {} - local countOfStrings = math.ceil(sText / textLimit) - for i=1, countOfStrings do - parsedErr[i] = unicode.sub(text, i * textLimit - textLimit + 1, i * textLimit) - end - - --Расчет высоты - local height = 6 - if #parsedErr > 1 then height = height + #parsedErr - 1 end - - --Расчет позиции окна - local xStart,yStart = ECSAPI.correctStartCoords("auto","auto",width,height) - local xEnd,yEnd = xStart + width - 1, yStart + height - 1 - - --Рисуем окно - local oldPixels = ECSAPI.emptyWindow(xStart,yStart,width,height," ") - - --Рисуем воскл знак - ECSAPI.drawCustomImage(xStart + 2,yStart + 2,image) - - --Рисуем текст ошибки - gpu.setBackground(ECSAPI.windowColors.background) - gpu.setForeground(ECSAPI.windowColors.usualText) - local xPos, yPos = xStart + 9, yStart + 2 - for i=1, #parsedErr do - gpu.set(xPos, yPos, parsedErr[i]) - yPos = yPos + 1 - end - - --Рисуем кнопу - local xButton = xEnd - unicode.len(buttonText) - 7 - local button = {ECSAPI.drawAdaptiveButton(xButton,yEnd - 1,3,0,buttonText,ECSAPI.colors.lightBlue,0xffffff)} - - --Ждем - while true do - local e = {event.pull()} - if e[1] == "touch" then - if ECSAPI.clickedAtArea(e[3],e[4],button[1],button[2],button[3],button[4]) then - ECSAPI.drawAdaptiveButton(button[1],button[2],3,0,buttonText,ECSAPI.colors.blue,0xffffff) - os.sleep(0.4) - break - end - elseif e[1] == "key_down" and e[4] == 28 then - ECSAPI.drawAdaptiveButton(button[1],button[2],3,0,buttonText,ECSAPI.colors.blue,0xffffff) - os.sleep(0.4) - break - end - end - - --Профит - ECSAPI.drawOldPixels(oldPixels) - -end - - -function ECSAPI.prepareToExit(color1, color2) - ECSAPI.clearScreen(color1 or 0x333333) - gpu.setForeground(color2 or 0xffffff) - gpu.set(1, 1, "") -end - ---А ЭТО КАРОЧ ИЗ ЮНИКОДА В СИМВОЛ - ВРОДЕ РАБОТАЕТ, НО ВСЯКОЕ БЫВАЕТ -function ECSAPI.convertCodeToSymbol(code) - local symbol - if code ~= 0 and code ~= 13 and code ~= 8 and code ~= 9 and code ~= 200 and code ~= 208 and code ~= 203 and code ~= 205 and not keyboard.isControlDown() then - symbol = unicode.char(code) - if keyboard.isShiftPressed then symbol = unicode.upper(symbol) end - end - return symbol -end - -function ECSAPI.progressBar(x, y, width, height, background, foreground, percent) - local activeWidth = math.ceil(width * percent / 100) - ECSAPI.square(x, y, width, height, background) - ECSAPI.square(x, y, activeWidth, height, foreground) -end - ---ВВОД ТЕКСТА ПО ЛИМИТУ ВО ВСЯКИЕ ПОЛЯ - УДОБНАЯ ШТУКА КАРОЧ -function ECSAPI.inputText(x, y, limit, cheBiloVvedeno, background, foreground, justDrawNotEvent, maskTextWith) - limit = limit or 10 - cheBiloVvedeno = cheBiloVvedeno or "" - background = background or 0xffffff - foreground = foreground or 0x000000 - - gpu.setBackground(background) - gpu.setForeground(foreground) - gpu.fill(x, y, limit, 1, " ") - - local text = cheBiloVvedeno - - local function draw() - term.setCursorBlink(false) - - local dlina = unicode.len(text) - local xCursor = x + dlina - if xCursor > (x + limit - 1) then xCursor = (x + limit - 1) end - - if maskTextWith then - gpu.set(x, y, ECSAPI.stringLimit("start", string.rep("●", dlina), limit)) - else - gpu.set(x, y, ECSAPI.stringLimit("start", text, limit)) - end - - term.setCursor(xCursor, y) - - term.setCursorBlink(true) - end - - draw() - - if justDrawNotEvent then term.setCursorBlink(false); return cheBiloVvedeno end - - while true do - local e = {event.pull()} - if e[1] == "key_down" then - if e[4] == 14 then - term.setCursorBlink(false) - text = unicode.sub(text, 1, -2) - if unicode.len(text) < limit then gpu.set(x + unicode.len(text), y, " ") end - draw() - elseif e[4] == 28 then - term.setCursorBlink(false) - return text - else - local symbol = ECSAPI.convertCodeToSymbol(e[3]) - if symbol then - text = text..symbol - draw() - end - end - elseif e[1] == "touch" then - term.setCursorBlink(false) - return text - end - end -end - -function ECSAPI.selector(x, y, limit, cheBiloVvedeno, varianti, background, foreground, justDrawNotEvent) +local copyright = [[ - local selectionHeight = #varianti - local oldPixels + Тут можно было бы написать кучу текста, мол, + вы не имеете прав на использование этой хуйни в + коммерческих целях и прочую чушь, навеянную нам + западной культурой. Но я же не пидор какой-то, верно? + + Просто помни, сука, что эту ОСь накодил Тимофеев Игорь, + ссылка на ВК: vk.com/id7799889 - - local obj = {} - local function newObj(class, name, ...) - obj[class] = obj[class] or {} - obj[class][name] = {...} - end - - local function drawPimpo4ka(color) - ECSAPI.colorTextWithBack(x + limit - 1, y, color, 0xffffff - color, "▼") - end - - local function drawText(color) - gpu.setForeground(color) - gpu.set(x, y, ECSAPI.stringLimit("start", cheBiloVvedeno, limit - 1)) - end - - local function drawSelection() - local yPos = y + 1 - oldPixels = ECSAPI.rememberOldPixels(x, yPos, x + limit + 1, yPos + selectionHeight + 1) - ECSAPI.windowShadow(x, yPos, limit, selectionHeight) - ECSAPI.square(x, yPos, limit, selectionHeight, background) - - gpu.setForeground(foreground) - for i = 1, #varianti do - gpu.set(x, y + i, varianti[i]) - newObj("selector", varianti[i], x, y + i, x + limit - 1) - end - end - - ECSAPI.square(x, y, limit, 1, background) - drawText(foreground) - drawPimpo4ka(background - 0x555555) - - if justDrawNotEvent then return cheBiloVvedeno end - - drawPimpo4ka(0xffffff) - drawSelection() - - while true do - local e = {event.pull()} - if e[1] == "touch" then - for key, val in pairs(obj["selector"]) do - if obj["selector"] and ECSAPI.clickedAtArea(e[3], e[4], obj["selector"][key][1], obj["selector"][key][2], obj["selector"][key][3], obj["selector"][key][2]) then - ECSAPI.square(x, obj["selector"][key][2], limit, 1, ECSAPI.colors.blue) - gpu.setForeground(0xffffff) - gpu.set(x, obj["selector"][key][2], key) - os.sleep(0.3) - ECSAPI.drawOldPixels(oldPixels) - cheBiloVvedeno = key - drawPimpo4ka(background - 0x555555) - ECSAPI.square(x, y, limit - 1, 1, background) - drawText(foreground) - - return cheBiloVvedeno - end - end - end - end -end - -function ECSAPI.input(x, y, limit, title, ...) - - local obj = {} - local function newObj(class, name, ...) - obj[class] = obj[class] or {} - obj[class][name] = {...} - end - - local activeData = 1 - local data = {...} - - local sizeOfTheLongestElement = 1 - for i = 1, #data do - sizeOfTheLongestElement = math.max(sizeOfTheLongestElement, unicode.len(data[i][2])) - end - - local width = 2 + sizeOfTheLongestElement + 2 + limit + 2 - local height = 2 + #data * 2 + 2 - - --ПО ЦЕНТРУ ЭКРАНА, А ТО МАЛО ЛИ ЧЕ - x, y = ECSAPI.correctStartCoords(x, y, width, height) - - local oldPixels = ECSAPI.rememberOldPixels(x, y, x + width + 1, y + height) - - ECSAPI.emptyWindow(x, y, width, height, title) - - local xPos, yPos - - local function drawElement(i, justDrawNotEvent) - xPos = x + 2 - yPos = y + i * 2 - local color = 0x666666 - if i == activeData then color = 0x000000 end - - gpu.setBackground(ECSAPI.windowColors.background) - ECSAPI.colorText(xPos, yPos, color, data[i][2]) - - xPos = (x + width - 2 - limit) - - local data1 - - if data[i][1] == "select" or data[i][1] == "selector" or data[i][1] == "selecttion" then - data1 = ECSAPI.selector(xPos, yPos, limit, data[i][3] or "", data[i][4] or {"What?", "Bad API use :("}, 0xffffff, color, justDrawNotEvent) - else - data1 = ECSAPI.inputText(xPos, yPos, limit, data[i][3] or "", 0xffffff, color, justDrawNotEvent) - end - - newObj("elements", i, xPos, yPos, xPos + limit - 1) - - return data1 - end - - local coodrs = { ECSAPI.drawAdaptiveButton(x + width - 10, y + height - 2, 3, 0, "OK", ECSAPI.colors.lightBlue, 0xffffff) } - newObj("OK", "OK", coodrs[1], coodrs[2], coodrs[3]) - - local function pressButton(press, press2) - if press then - ECSAPI.drawAdaptiveButton(obj["OK"]["OK"][1], obj["OK"]["OK"][2], 3, 0, "OK", press, press2) - else - ECSAPI.drawAdaptiveButton(obj["OK"]["OK"][1], obj["OK"]["OK"][2], 3, 0, "OK", ECSAPI.colors.lightBlue, 0xffffff) - end - end - - local function drawAll() - gpu.setBackground(ECSAPI.windowColors.background) - for i = 1, #data do - drawElement(i, true) - end - - if activeData > #data then - pressButton(ECSAPI.colors.blue, 0xffffff) - else - pressButton(false) - end - end - - local function getMassiv() - local massiv = {} - for i = 1, #data do - table.insert(massiv, data[i][3]) - end - return massiv - end - - local function drawKaro4() - if activeData ~= -1 then data[activeData][3] = drawElement(activeData, false) end - end - - ------------------------------------------------------------------------------------------------ - - drawAll() - drawKaro4() - activeData = activeData + 1 - drawAll() - - while true do - - local e = {event.pull()} - if e[1] == "key_down" then - - if e[4] == 28 and activeData > #data then pressButton(false); os.sleep(0.2); pressButton(ECSAPI.colors.blue, 0xffffff); break end - - if e[4] == 200 and activeData > 1 then activeData = activeData - 1; drawAll() end - if e[4] == 208 and activeData ~= -1 and activeData <= #data then activeData = activeData + 1; drawAll() end - - if e[4] == 28 then - drawKaro4() - if activeData <= #data and activeData ~= -1 then activeData = activeData + 1 end - drawAll() - end - - - - - elseif e[1] == "touch" then - for key, val in pairs(obj["elements"]) do - if ECSAPI.clickedAtArea(e[3], e[4], obj["elements"][key][1], obj["elements"][key][2], obj["elements"][key][3], obj["elements"][key][2]) then - - if key ~= activeData then activeData = key else drawKaro4(); if activeData <= #data then activeData = activeData + 1 end end - - drawAll() - --activeData = key - - --activeData = -1 - - --if activeData <= #data then activeData = activeData + 1 end - - break - end - end - - if ECSAPI.clickedAtArea(e[3], e[4], obj["OK"]["OK"][1], obj["OK"]["OK"][2], obj["OK"]["OK"][3], obj["OK"]["OK"][2]) then - - if activeData > #data then - pressButton(false); os.sleep(0.2); pressButton(ECSAPI.colors.blue, 0xffffff) - else - pressButton(ECSAPI.colors.blue, 0xffffff) - os.sleep(0.3) - end - - break - end - end - end - - ECSAPI.drawOldPixels(oldPixels) - - return getMassiv() -end - -function ECSAPI.getHDDs() - local candidates = {} - for address in component.list("filesystem") do - local dev = component.proxy(address) - if not dev.isReadOnly() and dev.address ~= computer.tmpAddress() and fs.get(os.getenv("_")).address then - table.insert(candidates, dev) - end - end - return candidates -end - -function ECSAPI.parseErrorMessage(error, translate) - - local parsedError = {} - - -- --ВСТАВКА ВСЕГО ГОВНА ДО ПЕРВОГО ЭНТЕРА - -- local starting, ending = string.find(error, "\n", 1) - -- table.insert(parsedError, unicode.sub(error, 1, ending or #error)) - - --ПОИСК ЭНТЕРОВ - local starting, ending, searchFrom = nil, nil, 1 - for i = 1, unicode.len(error) do - starting, ending = string.find(error, "\n", searchFrom) - if starting then - table.insert(parsedError, unicode.sub(error, searchFrom, starting - 1)) - searchFrom = ending + 1 - else - break - end - end - - --На всякий случай, если сообщение об ошибке без энтеров вообще, т.е. однострочное - if #parsedError == 0 and error ~= "" and error ~= nil and error ~= " " then - table.insert(parsedError, error) - end - - --Замена /r/n и табсов - for i = 1, #parsedError do - parsedError[i] = string.gsub(parsedError[i], "\r\n", "\n") - parsedError[i] = string.gsub(parsedError[i], " ", " ") - end - - if translate then - for i = 1, #parsedError do - parsedError[i] = string.gsub(parsedError[i], "interrupted", "Выполнение программы прервано пользователем") - parsedError[i] = string.gsub(parsedError[i], " got ", " получена ") - parsedError[i] = string.gsub(parsedError[i], " expected,", " ожидается,") - parsedError[i] = string.gsub(parsedError[i], "bad argument #", "Неверный аргумент №") - parsedError[i] = string.gsub(parsedError[i], "stack traceback", "Отслеживание ошибки") - parsedError[i] = string.gsub(parsedError[i], "tail calls", "Дочерние функции") - parsedError[i] = string.gsub(parsedError[i], "in function", "в функции") - parsedError[i] = string.gsub(parsedError[i], "in main chunk", "в основной программе") - parsedError[i] = string.gsub(parsedError[i], "unexpected symbol near", "неожиданный символ рядом с") - parsedError[i] = string.gsub(parsedError[i], "attempt to index", "несуществующий индекс") - parsedError[i] = string.gsub(parsedError[i], "attempt to get length of", "не удается получить длину") - parsedError[i] = string.gsub(parsedError[i], ": ", ", ") - parsedError[i] = string.gsub(parsedError[i], " module ", " модуль ") - parsedError[i] = string.gsub(parsedError[i], "not found", "не найден") - parsedError[i] = string.gsub(parsedError[i], "no field package.preload", "не найдена библиотека") - parsedError[i] = string.gsub(parsedError[i], "no file", "нет файла") - parsedError[i] = string.gsub(parsedError[i], "local", "локальной") - parsedError[i] = string.gsub(parsedError[i], "global", "глобальной") - parsedError[i] = string.gsub(parsedError[i], "no primary", "не найден компонент") - parsedError[i] = string.gsub(parsedError[i], "available", "в доступе") - parsedError[i] = string.gsub(parsedError[i], "attempt to concatenate", "не могу присоединить") - end - end - - starting, ending = nil, nil - - return parsedError -end - -function ECSAPI.displayCompileMessage(y, reason, translate, withAnimation) - - local xSize, ySize = gpu.getResolution() - - --Переводим причину в массив - reason = ECSAPI.parseErrorMessage(reason, translate) - - --Получаем ширину и высоту окошка - local width = math.floor(xSize * 7 / 10) - local height = #reason + 6 - local textWidth = width - 11 - - --Просчет вот этой хуйни, аааахаахах - local difference = ySize - (height + y) - if difference < 0 then - for i = 1, (math.abs(difference) + 1) do - table.remove(reason, 1) - end - table.insert(reason, 1, "…") - height = #reason + 6 - end - - local x = math.floor(xSize / 2 - width / 2) - - --Иконочка воскл знака на красном фоне - local errorImage = { - {{0xff0000,0xffffff,"#"},{0xff0000,0xffffff,"#"},{0xff0000,0xffffff," "},{0xff0000,0xffffff,"#"},{0xff0000,0xffffff,"#"}}, - {{0xff0000,0xffffff,"#"},{0xff0000,0xffffff," "},{0xff0000,0xffffff,"!"},{0xff0000,0xffffff," "},{0xff0000,0xffffff,"#"}}, - {{0xff0000,0xffffff," "},{0xff0000,0xffffff," "},{0xff0000,0xffffff," "},{0xff0000,0xffffff," "},{0xff0000,0xffffff," "}} - } - - --Запоминаем, че было отображено - local oldPixels = ECSAPI.rememberOldPixels(x, y, x + width + 1, y + height) - - --Типа анимация, ога - if withAnimation then - for i = 1, height, 1 do - ECSAPI.square(x, y, width, i, ECSAPI.windowColors.background) - ECSAPI.windowShadow(x, y, width, i) - os.sleep(0.01) - end - else - ECSAPI.square(x, y, width, height, ECSAPI.windowColors.background) - ECSAPI.windowShadow(x, y, width, height) - end - - --Рисуем воскл знак - ECSAPI.drawCustomImage(x + 2, y + 1, errorImage) - - --Рисуем текст - local yPos = y + 1 - local xPos = x + 9 - gpu.setBackground(ECSAPI.windowColors.background) - - ECSAPI.colorText(xPos, yPos, ECSAPI.windowColors.usualText, "Код ошибки:") - yPos = yPos + 2 - - gpu.setForeground( 0xcc0000 ) - for i = 1, #reason do - gpu.set(xPos, yPos, ECSAPI.stringLimit("end", reason[i], textWidth)) - yPos = yPos + 1 - end - - yPos = yPos + 1 - ECSAPI.colorText(xPos, yPos, ECSAPI.windowColors.usualText, ECSAPI.stringLimit("end", "Нажмите любую клавишу, чтобы продолжить", textWidth)) - - --Пикаем звуком кароч - for i = 1, 3 do - computer.beep(1000) - end - - --Ждем сам знаешь чего - ECSAPI.waitForTouchOrClick() - - --Рисуем, че было нарисовано - ECSAPI.drawOldPixels(oldPixels) -end - -function ECSAPI.select(x, y, title, textLines, buttons) - - --Ну обжекты, хули - local obj = {} - local function newObj(class, name, ...) - obj[class] = obj[class] or {} - obj[class][name] = {...} - end - - --Вычисление ширны на основе текста - local sizeOfTheLongestElement = 0 - for i = 1, #textLines do - sizeOfTheLongestElement = math.max(sizeOfTheLongestElement, unicode.len(textLines[i][1])) - end - - local width = sizeOfTheLongestElement + 4 - - --Вычисление ширины на основе размера кнопок - local buttonOffset = 2 - local spaceBetweenButtons = 2 - - local sizeOfButtons = 0 - for i = 1, #buttons do - sizeOfButtons = sizeOfButtons + unicode.len(buttons[i][1]) + buttonOffset * 2 + spaceBetweenButtons - end - - --Финальное задание ширины и высоты - width = math.max(width, sizeOfButtons + 2) - local height = #textLines + 5 - - --Рисуем окно - x, y = ECSAPI.correctStartCoords(x, y, width, height) - local oldPixels = ECSAPI.emptyWindow(x, y, width, height, title) - - --Рисуем текст - local xPos, yPos = x + 2, y + 2 - gpu.setBackground(ECSAPI.windowColors.background) - for i = 1, #textLines do - ECSAPI.colorText(xPos, yPos, textLines[i][2] or ECSAPI.windowColors.usualText, textLines[i][1] or "Ну ты че, текст-то введи!") - yPos = yPos + 1 - end - - --Рисуем кнопочки - xPos, yPos = x + width - sizeOfButtons, y + height - 2 - for i = 1, #buttons do - newObj("Buttons", buttons[i][1], ECSAPI.drawAdaptiveButton(xPos, yPos, buttonOffset, 0, buttons[i][1], buttons[i][2] or ECSAPI.colors.lightBlue, buttons[i][3] or 0xffffff)) - xPos = xPos + buttonOffset * 2 + spaceBetweenButtons + unicode.len(buttons[i][1]) - end - - --Жмякаем на кнопочки - local action - - while true do - if action then break end - local e = {event.pull()} - if e[1] == "touch" then - for key, val in pairs(obj["Buttons"]) do - if ECSAPI.clickedAtArea(e[3], e[4], obj["Buttons"][key][1], obj["Buttons"][key][2], obj["Buttons"][key][3], obj["Buttons"][key][4]) then - ECSAPI.drawAdaptiveButton(obj["Buttons"][key][1], obj["Buttons"][key][2], buttonOffset, 0, key, ECSAPI.colors.blue, 0xffffff) - os.sleep(0.3) - action = key - break - end - end - elseif e[1] == "key_down" then - if e[4] == 28 then - action = buttons[#buttons][1] - ECSAPI.drawAdaptiveButton(obj["Buttons"][action][1], obj["Buttons"][action][2], buttonOffset, 0, action, ECSAPI.colors.blue, 0xffffff) - os.sleep(0.3) - break - end - end - end - - ECSAPI.drawOldPixels(oldPixels) - - return action -end - -function ECSAPI.askForReplaceFile(path) - if fs.exists(path) then - action = ECSAPI.select("auto", "auto", " ", {{"Файл \"".. fs.name(path) .. "\" уже имеется в этом месте."}, {"Заменить его перемещаемым объектом?"}}, {{"Оставить оба", 0xffffff, 0x000000}, {"Отмена", 0xffffff, 0x000000}, {"Заменить"}}) - if action == "Оставить оба" then - return "keepBoth" - elseif action == "Отмена" then - return "cancel" - else - return "replace" - end - end -end - --- --Копирование файлов для операционки --- function ECSAPI.copy(from, to) --- local name = fs.name(from) --- local toName = to.."/"..name --- local action = ECSAPI.askForReplaceFile(toName) --- if action == nil or action == "replace" then --- fs.remove(toName) --- if fs.isDirectory(from) then --- ECSAPI.error("Копирование папок отключено во избежание перегрузки файловой системы. Мод говно, смирись.") --- else --- fs.copy(from, toName) --- end --- elseif action == "keepBoth" then --- if fs.isDirectory(from) then --- ECSAPI.error("Копирование папок отключено во избежание перегрузки файловой системы. Мод говно, смирись.") --- else --- fs.copy(from, fs.path(toName) .. "/(copy)"..fs.name(toName)) --- end --- end --- end - ---Переименование файлов для операционки -function ECSAPI.rename(mainPath) - local name = fs.name(mainPath) - path = fs.path(mainPath) - - --Рисуем окошко ввода нового имени файла - local inputs = ECSAPI.input("auto", "auto", 20, " ", {"input", "Новое имя", name}) - - --Если ввели в окошко хуйню какую-то - if inputs[1] == "" or inputs[1] == " " or inputs[1] == nil then - ECSAPI.error("Неверное имя файла.") - else - --Получаем новый путь к новому файлу - local newPath = path..inputs[1] - --Если файл с новым путем уже существует - if fs.exists(newPath) then - ECSAPI.error("Файл \"".. name .. "\" уже имеется в этом месте.") - return - else - fs.rename(mainPath, newPath) - end - end -end - ---Простое информационное окошечко -function ECSAPI.info(x, y, title, text) - x = x or "auto" - y = y or "auto" - title = title or " " - text = text or "Sample text" - - local width = unicode.len(text) + 4 - local height = 4 - x, y = ECSAPI.correctStartCoords(x, y, width, height) - - local oldPixels = ECSAPI.rememberOldPixels(x, y, x + width + 1, y + height) - - ECSAPI.emptyWindow(x, y, width, height, title) - ECSAPI.colorTextWithBack(x + 2, y + 2, ECSAPI.windowColors.usualText, ECSAPI.windowColors.background, text) - - return oldPixels -end - ---Скроллбар вертикальный -function ECSAPI.srollBar(x, y, width, height, countOfAllElements, currentElement, backColor, frontColor) - local sizeOfScrollBar = math.ceil(1 / countOfAllElements * height) - local displayBarFrom = math.floor(y + height * ((currentElement - 1) / countOfAllElements)) - - ECSAPI.square(x, y, width, height, backColor) - ECSAPI.square(x, displayBarFrom, width, sizeOfScrollBar, frontColor) - - sizeOfScrollBar, displayBarFrom = nil, nil -end - ---Поле с текстом. Сюда пихать массив вида {"строка1", "строка2", "строка3", ...} -function ECSAPI.textField(x, y, width, height, lines, displayFrom, background, foreground, scrollbarBackground, scrollbarForeground) - x, y = ECSAPI.correctStartCoords(x, y, width, height) - - background = background or 0xffffff - foreground = foreground or ECSAPI.windowColors.usualText - - local sLines = #lines - local lineLimit = width - 3 - - --Парсим строки - local line = 1 - while lines[line] do - local sLine = unicode.len(lines[line]) - if sLine > lineLimit then - local part1, part2 = unicode.sub(lines[line], 1, lineLimit), unicode.sub(lines[line], lineLimit + 1, -1) - lines[line] = part1 - table.insert(lines, line + 1, part2) - part1, part2 = nil, nil - end - line = line + 1 - sLine = nil - end - line = nil - - ECSAPI.square(x, y, width - 1, height, background) - ECSAPI.srollBar(x + width - 1, y, 1, height, sLines, displayFrom, scrollbarBackground, scrollbarForeground) - - gpu.setBackground(background) - gpu.setForeground(foreground) - local yPos = y - for i = displayFrom, (displayFrom + height - 1) do - if lines[i] then - gpu.set(x + 1, yPos, lines[i]) - yPos = yPos + 1 - else - break - end - end - - return sLines -end - -function ECSAPI.beautifulInput(x, y, width, title, buttonText, back, fore, otherColor, autoRedraw, ...) - - if not width or width < 30 then width = 30 end - data = {...} - local sData = #data - local height = 3 + sData * 3 + 1 - - x, y = ECSAPI.correctStartCoords(x, y, width, height) - local xCenter = math.floor(x + width / 2 - 1) - - local oldPixels = ECSAPI.rememberOldPixels(x, y, x + width - 1, y + height + 2) - - --Рисуем фон - ECSAPI.square(x, y, width, height, back) - --ECSAPI.windowShadow(x, y, width, height) - - local xText = x + 3 - local inputLimit = width - 6 - - --Авторизация - ECSAPI.drawButton(x, y, width, 3, title, back, fore) - - local fields - - local function drawData() - local i = y + 4 - - fields = {} - - for j = 1, sData do - ECSAPI.border(x + 1, i - 1, width - 2, 3, back, fore) - - if data[j][3] == "" or not data[j][3] or data[j][3] == " " then - ECSAPI.colorTextWithBack(xText, i, fore, back, data[j][1]) - else - if data[j][2] then - ECSAPI.inputText(xText, i, inputLimit, data[j][3], back, fore, true, true) - else - ECSAPI.inputText(xText, i, inputLimit, data[j][3], back, fore, true) - end - end - - table.insert(fields, { x + 1, i - 1, x + inputLimit - 1, i + 1 }) - - i = i + 3 - end - end - - local function getData() - local massiv = {} - for i = 1, sData do - table.insert(massiv, data[i][3]) - end - return massiv - end - - drawData() - - --Нижняя кнопа - local button = { ECSAPI.drawButton(x, y + sData * 3 + 4, width, 3, buttonText, otherColor, fore) } - - while true do - local e = {event.pull()} - if e[1] == "touch" then - if ECSAPI.clickedAtArea(e[3], e[4], button[1], button[2], button[3], button[4]) then - ECSAPI.drawButton(button[1], button[2], width, 3, buttonText, ECSAPI.colors.blue, 0xffffff) - os.sleep(0.3) - if autoRedraw then ECSAPI.drawOldPixels(oldPixels) end - return getData() - end - - for key, val in pairs(fields) do - if ECSAPI.clickedAtArea(e[3], e[4], fields[key][1], fields[key][2], fields[key][3], fields[key][4]) then - ECSAPI.border(fields[key][1], fields[key][2], width - 2, 3, back, otherColor) - data[key][3] = ECSAPI.inputText(xText, fields[key][2] + 1, inputLimit, "", back, fore, false, data[key][2]) - --ECSAPI.border(fields[key][1], fields[key][2], width - 2, 3, back, fore) - drawData() - break - end - end - elseif e[1] == "key_down" then - if e[4] == 28 then - ECSAPI.drawButton(button[1], button[2], width, 3, buttonText, ECSAPI.colors.blue, 0xffffff) - os.sleep(0.3) - if autoRedraw then ECSAPI.drawOldPixels(oldPixels) end - return getData() - end - end - end - -end - -function ECSAPI.beautifulSelect(x, y, width, title, buttonText, back, fore, otherColor, autoRedraw, ...) - if not width or width < 30 then width = 30 end - data = {...} - local sData = #data - local height = 3 + sData * 3 + 1 - - x, y = ECSAPI.correctStartCoords(x, y, width, height) - local xCenter = math.floor(x + width / 2 - 1) - - local oldPixels = ECSAPI.rememberOldPixels(x, y, x + width - 1, y + height + 2) - - --Рисуем фон - ECSAPI.square(x, y, width, height, back) - - local xText = x + 3 - local inputLimit = width - 9 - - --Первая кнопа - ECSAPI.drawButton(x, y, width, 3, title, back, fore) - - --Нижняя кнопа - local button = { ECSAPI.drawButton(x, y + sData * 3 + 4, width, 3, buttonText, otherColor, fore) } - - local fields - - local selectedData = 1 - local symbol = "✔" - - --Рисуем данные - local function drawData() - local i = y + 4 - - fields = {} - - for j = 1, sData do - - --Квадратик для галочки - ECSAPI.border(x + 1, i - 1, 5, 3, back, fore) - - --Галочку рисуем или снимаем - local text = " " - if j == selectedData then text = symbol end - ECSAPI.colorText(x + 3, i, otherColor, text) - - ECSAPI.colorText(x + 7, i, fore, ECSAPI.stringLimit("end", data[j], inputLimit)) - - table.insert(fields, { x + 1, i - 1, x + inputLimit - 1, i + 1 }) - - i = i + 3 - end - end - - drawData() - - while true do - local e = {event.pull()} - if e[1] == "touch" then - if ECSAPI.clickedAtArea(e[3], e[4], button[1], button[2], button[3], button[4]) then - ECSAPI.drawButton(button[1], button[2], width, 3, buttonText, ECSAPI.colors.blue, 0xffffff) - os.sleep(0.3) - if autoRedraw then ECSAPI.drawOldPixels(oldPixels) end - return data[selectedData] - end - - for key, val in pairs(fields) do - if ECSAPI.clickedAtArea(e[3], e[4], fields[key][1], fields[key][2], fields[key][3], fields[key][4]) then - selectedData = key - drawData() - break - end - end - elseif e[1] == "key_down" then - if e[4] == 28 then - ECSAPI.drawButton(button[1], button[2], width, 3, buttonText, ECSAPI.colors.blue, 0xffffff) - os.sleep(0.3) - if autoRedraw then ECSAPI.drawOldPixels(oldPixels) end - return data[selectedData] - end - end - end -end - ---Получение верного имени языка. Просто для безопасности. -function ECSAPI.getCorrectLangName(pathToLangs) - local language = _OSLANGUAGE .. ".lang" - if not fs.exists(pathToLangs .. "/" .. language) then - language = "English.lang" - end - return language -end - ---Чтение языкового файла -function ECSAPI.readCorrectLangFile(pathToLangs) - local lang - - local language = ECSAPI.getCorrectLangName(pathToLangs) - - lang = config.readAll(pathToLangs .. "/" .. language) - - return lang -end - - - - - - - - ----------------------------------------------------------------------------------------------------------------- - ---Получить данные о файле из ярлыка -function ECSAPI.readShortcut(path) - local success, filename = pcall(loadfile(path)) - if success then - return filename - else - error("Ошибка чтения файла ярлыка. Вероятно, он создан криво, либо не существует в папке " .. path) - end -end - ---Вся необходимая информация для иконок -local function OSIconsInit() - if not ECSAPI.OSIcons then - --Константы для иконок - ECSAPI.OSIcons = {} - ECSAPI.pathToIcons = "System/OS/Icons/" - ECSAPI.OSIconsWidth = 12 - ECSAPI.OSIconsHeight = 6 - --Иконки - ECSAPI.OSIcons.folder = image.load(ECSAPI.pathToIcons .. "Folder.png") - ECSAPI.OSIcons.script = image.load(ECSAPI.pathToIcons .. "Script.png") - ECSAPI.OSIcons.text = image.load(ECSAPI.pathToIcons .. "Text.png") - ECSAPI.OSIcons.config = image.load(ECSAPI.pathToIcons .. "Config.png") - ECSAPI.OSIcons.lua = image.load(ECSAPI.pathToIcons .. "Lua.png") - ECSAPI.OSIcons.image = image.load(ECSAPI.pathToIcons .. "Image.png") - ECSAPI.OSIcons.imageJPG = image.load(ECSAPI.pathToIcons .. "ImageJPG.png") - ECSAPI.OSIcons.pastebin = image.load(ECSAPI.pathToIcons .. "Pastebin.png") - ECSAPI.OSIcons.fileNotExists = image.load(ECSAPI.pathToIcons .. "FileNotExists.png") - end -end - ---Отрисовка одной иконки -function ECSAPI.drawOSIcon(x, y, path, showFileFormat) - --Инициализируем переменные иконок. Чисто для уменьшения расхода оперативки. - OSIconsInit() - --Получаем формат файла - local fileFormat = ECSAPI.getFileFormat(path) - --Создаем пустую переменную для конкретной иконки, для ее типа - local icon - --Если данный файл является папкой, то - if fs.isDirectory(path) then - if fileFormat == ".app" then - icon = path .. "/Resources/Icon.png" - --Если данной иконки еще нет в оперативке, то загрузить ее - if not ECSAPI.OSIcons[icon] then - ECSAPI.OSIcons[icon] = image.load(icon) - end - else - icon = "folder" - end - else - if fileFormat == ".lnk" then - local shortcutLink = ECSAPI.readShortcut(path) - drawIcon(x, y, shortcutLink) - ECSAPI.colorTextWithBack(x + ECSAPI.OSIconsWidth- 6, y + ECSAPI.OSIconsHeight - 3, 0x000000, 0xffffff, "⤶") - return 0 - elseif fileFormat == ".cfg" or fileFormat == ".config" then - icon = "config" - elseif fileFormat == ".txt" or fileFormat == ".rtf" then - icon = "text" - elseif fileFormat == ".lua" then - icon = "lua" - elseif fileFormat == ".png" then - icon = "image" - elseif fileFormat == ".jpg" then - icon = "imageJPG" - elseif fileFormat == ".paste" then - icon = "pastebin" - elseif not fs.exists(path) then - icon = "fileNotExists" - else - icon = "script" - end - end - - --Рисуем иконку - image.draw(x + 2, y, ECSAPI.OSIcons[icon]) - - --Делаем текст для иконки - local text = fs.name(path) - if not showFileFormat then - if fileFormat then - text = unicode.sub(text, 1, -(unicode.len(fileFormat) + 1)) - end - end - text = ECSAPI.stringLimit("end", text, ECSAPI.OSIconsWidth) - --Рассчитываем позицию текста - local textPos = x + math.floor(ECSAPI.OSIconsWidth / 2 - unicode.len(text) / 2) + 1 - --Рисуем текст под иконкой - ECSAPI.adaptiveText(x, y + ECSAPI.OSIconsHeight - 1, text, 0xffffff) - -end - ---ECSAPI.drawOSIcon(2, 2, "Pastebin1.app", true) - ----------------------------------------------------------------------------------------------------------------- - - ---Описание ниже, ебана -function ECSAPI.universalWindow(x, y, width, background, closeWindowAfter, ...) - local objects = {...} - local countOfObjects = #objects - - local pressedButton - - --Задаем высотные константы для объектов - local objectsHeights = { - ["button"] = 3, - ["centertext"] = 1, - ["emptyline"] = 1, - ["input"] = 3, - ["slider"] = 3, - ["select"] = 3, - ["selector"] = 3, - ["separator"] = 1, - } - - --Считаем высоту этой хуйни - local height = 0 - for i = 1, countOfObjects do - local objectType = string.lower(objects[i][1]) - if objectType == "select" then - height = height + (objectsHeights[objectType] * (#objects[i] - 3)) - elseif objectType == "textfield" then - height = height + objects[i][2] - else - height = height + objectsHeights[objectType] - end - end - - --Нужные стартовые прелесссти - x, y = ECSAPI.correctStartCoords(x, y, width, height) - local oldPixels = ECSAPI.rememberOldPixels(x, y, x + width - 1, y + height - 1) - - --Считаем все координаты объектов - objects[1].y = y - if countOfObjects > 1 then - for i = 2, countOfObjects do - local objectType = string.lower(objects[i - 1][1]) - if objectType == "select" then - objects[i].y = objects[i - 1].y + (objectsHeights[objectType] * (#objects[i - 1] - 3)) - elseif objectType == "textfield" then - objects[i].y = objects[i - 1].y + objects[i - 1][2] - else - objects[i].y = objects[i - 1].y + objectsHeights[objectType] - end - end - end - - --Объекты для тача - local obj = {} - local function newObj(class, name, ...) - obj[class] = obj[class] or {} - obj[class][name] = {...} - end - - --Отображение объекта по номеру - local function displayObject(number, active) - local objectType = string.lower(objects[number][1]) - - if objectType == "button" then - local back, fore, text = objects[number][2], objects[number][3], objects[number][4] - if active then - newObj("Buttons", number, ECSAPI.drawButton(x, objects[number].y, width, objectsHeights.button, text, fore, back)) - else - newObj("Buttons", number, ECSAPI.drawButton(x, objects[number].y, width, objectsHeights.button, text, back, fore)) - end - elseif objectType == "centertext" then - local xPos = x + math.floor(width / 2 - unicode.len(objects[number][3]) / 2) - gpu.setForeground(objects[number][2]) - gpu.set(xPos, objects[number].y, objects[number][3]) - - elseif objectType == "input" then - - if active then - --Рамочка - ECSAPI.border(x + 1, objects[number].y, width - 2, objectsHeights.input, background, objects[number][3]) - --Тестик - objects[number][4] = ECSAPI.inputText(x + 3, objects[number].y + 1, width - 6, "", background, objects[number][3], false, objects[number][5]) - else - --Рамочка - ECSAPI.border(x + 1, objects[number].y, width - 2, objectsHeights.input, background, objects[number][2]) - --Текстик - gpu.set(x + 3, objects[number].y + 1, ECSAPI.stringLimit("start", objects[number][4], width - 6)) - end - - newObj("Inputs", number, x + 1, objects[number].y, x + width - 2, objects[number].y + 2) - - elseif objectType == "slider" then - local widthOfSlider = width - 2 - local xOfSlider = x + 1 - local yOfSlider = objects[number].y + 1 - local countOfSliderThings = objects[number][5] - objects[number][4] - local showSliderValue = objects[number][7] - - local dolya = widthOfSlider / countOfSliderThings - local position = math.floor(dolya * objects[number][6]) - --Костыль - if (xOfSlider + position) > (xOfSlider + widthOfSlider - 1) then position = widthOfSlider - 2 end - - --Две линии - ECSAPI.separator(xOfSlider, yOfSlider, position, background, objects[number][3]) - ECSAPI.separator(xOfSlider + position, yOfSlider, widthOfSlider - position, background, objects[number][2]) - --Слудир - ECSAPI.square(xOfSlider + position, yOfSlider, 2, 1, objects[number][3]) - - --Текстик под слудиром - if showSliderValue then - local text = showSliderValue .. tostring(objects[number][6]) - local textPos = (xOfSlider + widthOfSlider / 2 - unicode.len(text) / 2) - ECSAPI.square(x, yOfSlider + 1, width, 1, background) - ECSAPI.colorText(textPos, yOfSlider + 1, objects[number][2], text) - end - - newObj("Sliders", number, xOfSlider, yOfSlider, x + widthOfSlider, yOfSlider, dolya) - - elseif objectType == "select" then - local usualColor = objects[number][2] - local selectionColor = objects[number][3] - - objects[number].selectedData = objects[number].selectedData or 1 - - local symbol = "✔" - local yPos = objects[number].y - for i = 4, #objects[number] do - --Коробка для галочки - ECSAPI.border(x + 1, yPos, 5, 3, background, usualColor) - --Текст - gpu.set(x + 7, yPos + 1, objects[number][i]) - --Галочка - if objects[number].selectedData == (i - 3) then - ECSAPI.colorText(x + 3, yPos + 1, selectionColor, symbol) - else - gpu.set(x + 3, yPos + 1, " ") - end - - obj["Selects"] = obj["Selects"] or {} - obj["Selects"][number] = obj["Selects"][number] or {} - obj["Selects"][number][i - 3] = { x + 1, yPos, x + width - 2, yPos + 2 } - - yPos = yPos + objectsHeights.select - end - - elseif objectType == "selector" then - local borderColor = objects[number][2] - local arrowColor = objects[number][3] - local selectorWidth = width - 2 - objects[number].selectedElement = objects[number].selectedElement or objects[number][4] - - local topLine = "┌" .. string.rep("─", selectorWidth - 6) .. "┬───┐" - local midLine = "│" .. string.rep(" ", selectorWidth - 6) .. "│ │" - local botLine = "└" .. string.rep("─", selectorWidth - 6) .. "┴───┘" - - local yPos = objects[number].y - - local function bordak(borderColor) - gpu.setBackground(background) - gpu.setForeground(borderColor) - gpu.set(x + 1, objects[number].y, topLine) - gpu.set(x + 1, objects[number].y + 1, midLine) - gpu.set(x + 1, objects[number].y + 2, botLine) - gpu.set(x + 3, objects[number].y + 1, ECSAPI.stringLimit("start", objects[number].selectedElement, width - 6)) - ECSAPI.colorText(x + width - 4, objects[number].y + 1, arrowColor, "▼") - end - - bordak(borderColor) - - --Выпадающий список, самый гемор, блядь - if active then - local xPos, yPos = x + 2, objects[number].y + 3 - local spisokWidth = width - 4 - local countOfElements = #objects[number] - 3 - local spisokHeight = countOfElements - local oldPixels = ECSAPI.rememberOldPixels( xPos, yPos, xPos + spisokWidth - 1, yPos + spisokHeight - 1) - - local coords = {} - - bordak(arrowColor) - - --Белый фоник рисуем-с - ECSAPI.square( xPos, yPos, spisokWidth, spisokHeight, 0xffffff ) - xPos = xPos + 1 - for i = 1, countOfElements do - ECSAPI.colorText(xPos, yPos, 0x000000, ECSAPI.stringLimit("start", objects[number][i + 3], spisokWidth - 2)) - coords[i] = {xPos - 1, yPos, xPos + spisokWidth - 1, yPos} - yPos = yPos + 1 - end - - --Обработка - local exit - while true do - if exit then break end - local e = {event.pull()} - if e[1] == "touch" then - for i = 1, #coords do - if ECSAPI.clickedAtArea(e[3], e[4], coords[i][1], coords[i][2], coords[i][3], coords[i][4]) then - ECSAPI.square(coords[i][1], coords[i][2], spisokWidth, 1, ECSAPI.colors.blue) - ECSAPI.colorText(coords[i][1] + 1, coords[i][2], 0xffffff, objects[number][i + 3]) - os.sleep(0.3) - objects[number].selectedElement = objects[number][i + 3] - exit = true - break - end - end - end - end - - ECSAPI.drawOldPixels(oldPixels) - end - - newObj("Selectors", number, x + 1, objects[number].y, x + width - 2, objects[number].y + 2) - - elseif objectType == "separator" then - ECSAPI.separator(x, objects[number].y, width, background, objects[number][2]) - - elseif objectType == "textfield" then - objects[number].displayFrom = objects[number].displayFrom or 1 - ECSAPI.textField(x + 1, objects[number].y, width - 2, objects[number][2], objects[number][7], objects[number].displayFrom, objects[number][3], objects[number][4], objects[number][5], objects[number][6]) - end - end - - --Отображение всех объектов - local function displayAllObjects() - for i = 1, countOfObjects do - displayObject(i) - end - end - - --Подготовить массив возвращаемый - local function getReturn() - local massiv = {} - - for i = 1, countOfObjects do - local type = string.lower(objects[i][1]) - - if type == "button" then - table.insert(massiv, pressedButton) - elseif type == "input" then - table.insert(massiv, objects[i][4]) - elseif type == "select" then - table.insert(massiv, objects[i].selectedData) - elseif type == "selector" then - table.insert(massiv, objects[i].selectedElement) - elseif type == "slider" then - table.insert(massiv, objects[i][6]) - else - table.insert(massiv, nil) - end - end - - return massiv - end - - --Рисуем окно - ECSAPI.square(x, y, width, height, background) - displayAllObjects() - - while true do - local e = {event.pull()} - if e[1] == "touch" or event == "drag" then - - --ECSAPI.error("x1 = "..obj["Buttons"][3][1]..", y1 = "..obj["Buttons"][3][2]..", e3 = "..e[3]..", e4 = "..e[4]) - - --Анализируем клик на кнопки - if obj["Buttons"] then - for key in pairs(obj["Buttons"]) do - if ECSAPI.clickedAtArea(e[3], e[4], obj["Buttons"][key][1], obj["Buttons"][key][2], obj["Buttons"][key][3], obj["Buttons"][key][4]) then - displayObject(key, true) - os.sleep(0.3) - pressedButton = objects[key][4] - if closeWindowAfter then ECSAPI.drawOldPixels(oldPixels) end - return getReturn() - end - end - end - - --А теперь клик на инпуты! - if obj["Inputs"] then - for key in pairs(obj["Inputs"]) do - if ECSAPI.clickedAtArea(e[3], e[4], obj["Inputs"][key][1], obj["Inputs"][key][2], obj["Inputs"][key][3], obj["Inputs"][key][4]) then - displayObject(key, true) - displayObject(key) - break - end - end - end - - --А теперь галочковыбор! - if obj["Selects"] then - for key in pairs(obj["Selects"]) do - for i in pairs(obj["Selects"][key]) do - if ECSAPI.clickedAtArea(e[3], e[4], obj["Selects"][key][i][1], obj["Selects"][key][i][2], obj["Selects"][key][i][3], obj["Selects"][key][i][4]) then - objects[key].selectedData = i - displayObject(key) - break - end - end - end - end - - --Хм, а вот и селектор подъехал! - if obj["Selectors"] then - for key in pairs(obj["Selectors"]) do - if ECSAPI.clickedAtArea(e[3], e[4], obj["Selectors"][key][1], obj["Selectors"][key][2], obj["Selectors"][key][3], obj["Selectors"][key][4]) then - displayObject(key, true) - displayObject(key) - break - end - end - end - - --Слайдеры, епта! "Потный матан", все делы - if obj["Sliders"] then - for key in pairs(obj["Sliders"]) do - if ECSAPI.clickedAtArea(e[3], e[4], obj["Sliders"][key][1], obj["Sliders"][key][2], obj["Sliders"][key][3], obj["Sliders"][key][4]) then - local xOfSlider, dolya = obj["Sliders"][key][1], obj["Sliders"][key][5] - local currentPixels = e[3] - xOfSlider - local currentValue = math.floor(currentPixels / dolya) - --Костыль - if e[3] == obj["Sliders"][key][3] then currentValue = objects[key][5] end - objects[key][6] = currentValue - displayObject(key) - break - end - end - end - end - end -end - ---local strings = {"Hello world! This is a test string and I'm so happy to show it!", "Awesome! It works!", "Cool!"} - --- ECSAPI.prepareToExit() --- --ECSAPI.universalWindow("auto", "auto", 30, ECSAPI.windowColors.background, true, {"EmptyLine"}, {"CenterText", 0x262626, "Хелло пидар!"}, {"EmptyLine"}, {"Input", 0x262626, 0x000000, "Суда вводи"}, {"Selector", 0x262626, 0x880000, "PNG", "JPG", "PSD"}, {"Slider", 0x262626, 0x880000, 0, 100, 50}, {"Select", 0x262626, 0x880000, "Выбор1", "Выбор2"}, {"EmptyLine"}, {"Button", 0xbbbbbb, 0xffffff, "Ok!"}) --- local data = ECSAPI.universalWindow("auto", "auto", 30, ECSAPI.windowColors.background, true, {"EmptyLine"}, {"CenterText", 0x262626, "Хелло пидар!"}, {"EmptyLine"}, {"Input", 0x262626, 0x880000, "Суда вводи"}, {"Selector", 0x262626, 0x880000, "PNG", "JPG", "PSD"}, {"Slider", 0x262626, 0x880000, 0, 100, 50, "Количество: "}, {"Select", 0x262626, 0x880000, "Выбор1", "Выбор2"}, {"EmptyLine"}, {"Button", 0xbbbbbb, 0xffffff, "Ok!"}) --- ECSAPI.prepareToExit() --- print(table.unpack(data)) - - ---[[ -Функция universalWindow(x, y, width, background, closeWindowAfter, ...) - Это универсальная модульная функция для максимально удобного и быстрого - отображения необходимой вам информации. С ее помощью вводить данные - с клавиатуры, осуществлять выбор из предложенных вариантов, рисовать - красивые кнопки, отрисовывать обычный текст, отрисовывать текстовые - поля с возможностью прокрутки, рисовать разделители и прочее. - Любой объект выделяется с помощью клика мыши, после чего функция - приступает к работе с этим объектом. - - Аргументы функции: - x и y: - Это числа, обозначающие стартовые координаты левого верхнего угла - данного окна. - Вместо цифр вы также можете написать "auto" - и программа - автоматически разместит окно по центру экрана по выбранной - координате. Или по обеим координатам, если вам угодно. - - width: - Это ширина окна, которую вы можете задать по собственному желанию. - Если некторые объекты требуют расширения окна, то окно будет - автоматически расширено до нужной ширины. Да, вот такая вот тавтология ;) - - background: - Базовый цвет окна (цвет фона, кому как понятнее). - - closeWindowAfter: - Если true, то окно по завершению функции будет выгружено, а на его месте отрисуются пиксели, - которые имелись на экране до выполнения функции. Удобно, если не хочешь париться - с перерисовкой интерфейса. - - ...: - Многоточием тут является перечень объектов, указанных через запятую. - Каждый объект является массивом и имеет собственный формат. - Ниже перечислены все типы объектов: - {"Button", Цвет кнопки, Цвет текста на кнопке, Сам текст} - {"Selector", Цвет рамки, Цвет стрелки, Выбор 1, Выбор 2, Выбор 3 ...} - {"Input", Цвет рамки и текста, Цвет при выделении, Стартовый текст, Маскировать символом} - {"Select", Цвет рамки, Цвет галочки, Выбор 1, Выбор 2, Выбор 3 ...} - {"TextField", Высота, Цвет фона, Цвет текста, Цвет скроллбара, Цвет пимпочки скроллбара, Массив со строками} - {"CenterText", Цвет текста, Сам текст} - {"Separator", Цвет разделителя} - {"Slider", Цвет линии слайдера, Цвет пимпочки слайдера, Значения слайдера ОТ, Значения слайдера ДО, Текущее значение, Текст-подсказка} - {"Switch", Цвет актива, Цвет пассива, Цвет текста, Текст, Изначальное состояние} - {"EmptyLine"} - Каждый из объектов рисуется по порядку сверху вниз. Каждый объект автоматически - увеличивает высоту окна до необходимого значения. - - Что возвращает функция: - Возвратом является массив, пронумерованный от 1 до <количества объектов>. - К примеру, 1 индекс данного массива соответствует 1 указанному объекту. - Каждый индекс данного массива несет в себе какие-то данные, которые вы - внесли в объект во время работы функции. - Например, если в 1-ый объект типа "Input" вы ввели фразу "Hello world", - то первый индекс в возвращенном массиве будет равен "Hello world". - Конкретнее это будет вот так: massiv[1] = "Hello world". - - Если взаимодействие с объектом невозможно - например, как с EmptyLine или - CenterText, то в возвращенном массиве этот элемент будет равен nil. - - Готовые примеры использования функции: ]] +local component = require("component") +local event = require("event") +local term = require("term") +local unicode = require("unicode") +--local ecs = require("ECSAPI") +--local fs = require("filesystem") +--local shell = require("shell") +local context = require("context") +local computer = require("computer") +local keyboard = require("keyboard") +--local image = require("image") +--local config = require("config") +local zip = require("zip") +local gpu = component.gpu +local internet = require("internet") + +--Загружаем языковой пакетик чайный +local lang = config.readAll("System/OS/Languages/".._G._OSLANGUAGE..".lang") + +------------------------------------------------------------------------------------------------------------------------ + +-- Ну, тут ваще изи все +local xSize, ySize = gpu.getResolution() + +-- Это все для раб стола +local icons = {} +local workPath = "" +local workPathHistory = {} +local clipboard +local currentFileList +local currentDesktop = 1 +local countOfDesktops + +--ЗАГРУЗКА ИКОНОК +icons["folder"] = image.load("System/OS/Icons/Folder.png") +icons["script"] = image.load("System/OS/Icons/Script.png") +icons["text"] = image.load("System/OS/Icons/Text.png") +icons["config"] = image.load("System/OS/Icons/Config.png") +icons["lua"] = image.load("System/OS/Icons/Lua.png") +icons["image"] = image.load("System/OS/Icons/Image.png") +icons["imageJPG"] = image.load("System/OS/Icons/ImageJPG.png") +icons["pastebin"] = image.load("System/OS/Icons/Pastebin.png") + +--ПЕРЕМЕННЫЕ ДЛЯ ДОКА +local dockColor = 0xcccccc +local heightOfDock = 4 +local background = 0x262626 +local currentCountOfIconsInDock = 4 +local pathOfDockShortcuts = "System/OS/Dock/" + +--ПЕРЕМЕННЫЕ, КАСАЮЩИЕСЯ ИКОНОК +local widthOfIcon = 12 +local heightOfIcon = 6 +local xSpaceBetweenIcons = 2 +local ySpaceBetweenIcons = 1 +local xCountOfIcons = math.floor(xSize / (widthOfIcon + xSpaceBetweenIcons)) +local yCountOfIcons = math.floor((ySize - (heightOfDock + 6)) / (heightOfIcon + ySpaceBetweenIcons)) +local totalCountOfIcons = xCountOfIcons * yCountOfIcons +local iconsSelectionColor = ecs.colors.lightBlue +--local yPosOfIcons = math.floor((ySize - heightOfDock - 2) / 2 - (yCountOfIcons * (heightOfIcon + ySpaceBetweenIcons) - ySpaceBetweenIcons * 2) / 2) +local yPosOfIcons = 3 +local xPosOfIcons = math.floor(xSize / 2 - (xCountOfIcons * (widthOfIcon + xSpaceBetweenIcons) - xSpaceBetweenIcons*4) / 2) + +local dockCountOfIcons = xCountOfIcons - 1 + +--ПЕРЕМЕННЫЕ ДЛЯ ТОП БАРА +local topBarColor = 0xdddddd +local showHiddenFiles = false +local showSystemFiles = false +local showFileFormat = false + +------------------------------------------------------------------------------------------------------------------------ + +--СОЗДАНИЕ ОБЪЕКТОВ +local obj = {} +local function newObj(class, name, ...) + obj[class] = obj[class] or {} + obj[class][name] = {...} +end + + +-- Не забудь потом сделат общее апи для гитхаба - а то что за копипаста? +-- Непорядок! +-- ЗАГРУЗОЧКА С ГИТХАБА +local function getFromGitHub(url, path) + local sContent = "" + local result, response = pcall(internet.request, url) + if not result then + return nil + end + + fs.remove(path) + fs.makeDirectory(fs.path(path)) + local file = io.open(path, "w") + + for chunk in response do + file:write(chunk) + sContent = sContent .. chunk + end + + file:close() + + return sContent +end + +--БЕЗОПАСНАЯ ЗАГРУЗОЧКА +local function getFromGitHubSafely(url, path) + local success, sRepos = pcall(getFromGitHub, url, path) + if not success then + --ecs.error("Could not connect to the Internet. Please ensure you have an Internet connection.") + return false, sRepos + end + return sRepos +end + +--Создать ярлык для конкретной проги +local function createShortCut(path, pathToProgram) + fs.remove(path) + fs.makeDirectory(fs.path(path)) + local file = io.open(path, "w") + file:write("return ", "\"", pathToProgram, "\"") + file:close() +end + +--Создать ярлык для конкретной пасты +local function createPastebinShortcut(path, pastebinLink) + fs.remove(path) + fs.makeDirectory(fs.path(path)) + local file = io.open(path .. "/"..pastebinLink .. ".paste", "w") + file:write("return ", "\"", pastebinLink, "\"") + file:close() +end + +-- НАРИСОВАТЬ ВЫДЕЛЕНИЕ ИКОНКИ +local function drawIconSelection(x, y, nomer) + if obj["DesktopIcons"][nomer][6] == true then + ecs.square(x - 2, y, widthOfIcon, heightOfIcon, iconsSelectionColor) + elseif obj["DesktopIcons"][nomer][6] == false then + ecs.square(x - 2, y, widthOfIcon, heightOfIcon, background) + end +end + +-- Развидеть все +local function deselectAll(mode) + for key, val in pairs(obj["DesktopIcons"]) do + if not mode then + if obj["DesktopIcons"][key][6] == true then + obj["DesktopIcons"][key][6] = false + end + else + if obj["DesktopIcons"][key][6] == false then + obj["DesktopIcons"][key][6] = nil + end + end + end +end + +------------------------------------------------------------------------------------------------ + +--То, что не нужно отрисовывать +local systemFiles = { + "bin/", + "lib/", + "OS.lua", + "autorun.lua", + "init.lua", + "tmp/", + "usr/", + "mnt/", + "etc/", + "boot/", + --"System/", +} + +-- Потная штучка, надо будет перекодить - а то странно выглядит, да и условия идиотские +local function reorganizeFilesAndFolders(massivSudaPihay, showHiddenFiles, showSystemFiles) + + local massiv = {} + + for i = 1, #massivSudaPihay do + if ecs.isFileHidden(massivSudaPihay[i]) and showHiddenFiles then + table.insert(massiv, massivSudaPihay[i]) + end + end + + for i = 1, #massivSudaPihay do + local cyka = massivSudaPihay[i] + if fs.isDirectory(cyka) and not ecs.isFileHidden(cyka) and ecs.getFileFormat(cyka) ~= ".app" then + table.insert(massiv, cyka) + end + cyka = nil + end + + for i = 1, #massivSudaPihay do + local cyka = massivSudaPihay[i] + if (not fs.isDirectory(cyka) and not ecs.isFileHidden(cyka)) or (fs.isDirectory(cyka) and not ecs.isFileHidden(cyka) and ecs.getFileFormat(cyka) == ".app") then + table.insert(massiv, cyka) + end + cyka = nil + end + + + if not showSystemFiles then + if workPath == "" or workPath == "/" then + --ecs.error("Сработало!") + local i = 1 + while i <= #massiv do + for j = 1, #systemFiles do + --ecs.error("massiv[i] = " .. massiv[i] .. ", systemFiles[j] = "..systemFiles[j]) + if massiv[i] == systemFiles[j] then + --ecs.error("Удалено! massiv[i] = " .. massiv[i] .. ", systemFiles[j] = "..systemFiles[j]) + table.remove(massiv, i) + i = i - 1 + break + end + + end + + i = i + 1 + end + end + end + + return massiv +end + +------------------------------------------------------------------------------------------------ + +--ОТРИСОВКА ИКОНОК НА РАБОЧЕМ СТОЛЕ ПО ТЕКУЩЕЙ ПАПКЕ +local function drawDesktop(x, y) + + currentFileList = ecs.getFileList(workPath) + currentFileList = reorganizeFilesAndFolders(currentFileList, showHiddenFiles, showSystemFiles) + + --ОЧИСТКА СТОЛА + ecs.square(1, y, xSize, yCountOfIcons * (heightOfIcon + ySpaceBetweenIcons) - ySpaceBetweenIcons, background) + + --ОЧИСТКА ОБЪЕКТОВ ИКОНОК + obj["DesktopIcons"] = {} + + --ОТРИСОВКА КНОПОЧЕК ПЕРЕМЕЩЕНИЯ + countOfDesktops = math.ceil(#currentFileList / totalCountOfIcons) + local xButtons, yButtons = math.floor(xSize / 2 - ((countOfDesktops + 1) * 3 - 3) / 2), ySize - heightOfDock - 3 + + --Очистка серым фоном всех кнопочек + ecs.square(1, yButtons, xSize, 1, background) + + --Отрисовка кнопки "Назад" + if #workPathHistory > 0 then + ecs.colorTextWithBack(xButtons, yButtons, 0x262626, 0xffffff, " <") + newObj("DesktopButtons", 0, xButtons, yButtons, xButtons + 1, yButtons) + xButtons = xButtons + 3 + end + + --Отрисовка остальных кнопочек + for i = 1, countOfDesktops do + local color = 0xffffff + + if i == currentDesktop then + color = ecs.colors.green + else + color = 0xffffff + end + + ecs.colorTextWithBack(xButtons, yButtons, 0x000000, color, " ") + newObj("DesktopButtons", i, xButtons, yButtons, xButtons + 1, yButtons) + + xButtons = xButtons + 3 + end + + --ОТРИСОВКА ИКОНОК ПО ФАЙЛ ЛИСТУ + local counter = currentDesktop * totalCountOfIcons - totalCountOfIcons + 1 + local xIcons, yIcons = x, y + for i = 1, yCountOfIcons do + for j = 1, xCountOfIcons do + if not currentFileList[counter] then break end + + --ОТРИСОВКА КОНКРЕТНОЙ ИКОНКИ + local path = workPath .. currentFileList[counter] + --drawIconSelection(xIcons, yIcons, counter) + ecs.drawOSIcon(xIcons, yIcons, path, showFileFormat) + + --СОЗДАНИЕ ОБЪЕКТА ИКОНКИ + newObj("DesktopIcons", counter, xIcons, yIcons, xIcons + widthOfIcon - 1, yIcons + heightOfIcon - 1, path, nil) + + xIcons = xIcons + widthOfIcon + xSpaceBetweenIcons + counter = counter + 1 + end + + xIcons = x + yIcons = yIcons + heightOfIcon + ySpaceBetweenIcons + end +end + +--ОТРИСОВКА ДОКА +local function drawDock() + + --Очистка объектов дока + obj["DockIcons"] = {} + + --ПОЛУЧИТЬ СПИСОК ЯРЛЫКОВ НА ДОКЕ + local dockShortcuts = ecs.getFileList(pathOfDockShortcuts) + currentCountOfIconsInDock = #dockShortcuts + + --ПОДСЧИТАТЬ РАЗМЕР ДОКА И ПРОЧЕЕ + local widthOfDock = (currentCountOfIconsInDock * (widthOfIcon + xSpaceBetweenIcons) - xSpaceBetweenIcons) + heightOfDock * 2 + 2 + local xDock, yDock = math.floor(xSize / 2 - widthOfDock / 2) + 1, ySize - heightOfDock + + --Закрасить все фоном + ecs.square(1, yDock - 1, xSize, heightOfDock + 2, background) + + --НАРИСОВАТЬ ПОДЛОЖКУ + local color = dockColor + for i = 1, heightOfDock do + ecs.square(xDock + i, ySize - i + 1, widthOfDock - i * 2, 1, color) + color = color - 0x181818 + end + + --НАРИСОВАТЬ ЯРЛЫКИ НА ДОКЕ + if currentCountOfIconsInDock > 0 then + local xIcons = math.floor(xSize / 2 - ((widthOfIcon + xSpaceBetweenIcons) * currentCountOfIconsInDock - xSpaceBetweenIcons * 4) / 2 ) + local yIcons = ySize - heightOfDock - 1 + + for i = 1, currentCountOfIconsInDock do + ecs.drawOSIcon(xIcons, yIcons, pathOfDockShortcuts..dockShortcuts[i], showFileFormat) + newObj("DockIcons", dockShortcuts[i], xIcons - 2, yIcons, xIcons + widthOfIcon - 1, yIcons + heightOfIcon - 1) + xIcons = xIcons + xSpaceBetweenIcons + widthOfIcon + end + end +end + +--РИСОВАТЬ ВРЕМЯ СПРАВА +local function drawTime() + local time = " " .. unicode.sub(os.date("%T"), 1, -4) .. " " + local sTime = unicode.len(time) + ecs.colorTextWithBack(xSize - sTime, 1, 0x000000, topBarColor, time) +end + +--РИСОВАТЬ ВЕСЬ ТОПБАР +local function drawTopBar() + + --Элементы топбара + local topBarElements = { "MineOS", lang.viewTab } + + --Белая горизонтальная линия + ecs.square(1, 1, xSize, 1, topBarColor) + + --Рисуем элементы и создаем объекты + local xPos = 2 + gpu.setForeground(0x000000) + for i = 1, #topBarElements do + + if i > 1 then gpu.setForeground(0x666666) end + + local length = unicode.len(topBarElements[i]) + gpu.set(xPos + 1, 1, topBarElements[i]) + + newObj("TopBarButtons", topBarElements[i], xPos, 1, xPos + length + 1, 1) + + xPos = xPos + length + 2 + end + + --Рисуем время + drawTime() +end + +--РИСОВАТЬ ВАЩЕ ВСЕ СРАЗУ +local function drawAll() + ecs.clearScreen(background) + drawTopBar() + drawDock() + drawDesktop(xPosOfIcons, yPosOfIcons) +end + +--ПЕРЕРИСОВАТЬ ВЫДЕЛЕННЫЕ ИКОНКИ +local function redrawSelectedIcons() + + for key, value in pairs(obj["DesktopIcons"]) do + + if obj["DesktopIcons"][key][6] ~= nil then + + local x = obj["DesktopIcons"][key][1] + local y = obj["DesktopIcons"][key][2] + + drawIconSelection(x, y, key) + ecs.drawOSIcon(x, y, obj["DesktopIcons"][key][5], showFileFormat) + + end + end +end + +--ВЫБРАТЬ ИКОНКУ И ВЫДЕЛИТЬ ЕЕ +local function selectIcon(nomer) + if keyboard.isControlDown() and not obj["DesktopIcons"][nomer][6] then + obj["DesktopIcons"][nomer][6] = true + redrawSelectedIcons() + elseif keyboard.isControlDown() and obj["DesktopIcons"][nomer][6] then + obj["DesktopIcons"][nomer][6] = false + redrawSelectedIcons() + elseif not keyboard.isControlDown() then + deselectAll() + obj["DesktopIcons"][nomer][6] = true + redrawSelectedIcons() + deselectAll(true) + end +end + +--ЗАПУСТИТЬ ПРОГУ +local function launchIcon(path, arguments) + + --Запоминаем, какое разрешение было + local oldWidth, oldHeight = gpu.getResolution() + + --Создаем нормальные аргументы для Шелла + if arguments then arguments = " " .. arguments else arguments = "" end + + --Получаем файл формат заранее + local fileFormat = ecs.getFileFormat(path) + + --Если это приложение + if fileFormat == ".app" then + ecs.prepareToExit() + local cyka = path .. "/" .. ecs.hideFileFormat(fs.name(path)) .. ".lua" + local success, reason = shell.execute(cyka) + ecs.prepareToExit() + if not success then ecs.displayCompileMessage(1, reason, true) end + + --Если это обычный луа файл - т.е. скрипт + elseif fileFormat == ".lua" or fileFormat == nil then + ecs.prepareToExit() + local success, reason = shell.execute(path .. arguments) + ecs.prepareToExit() + if success then + print(lang.programSuccessfullyExecuted) + else + ecs.displayCompileMessage(1, reason, true) + end + + --Если это фоточка + elseif fileFormat == ".png" then + shell.execute("Photoshop.app/Photoshop.lua open "..path) + + --Если это фоточка + elseif fileFormat == ".jpg" then + shell.execute("Photoshop.app/Photoshop.lua open "..path) + + --Если это текст или конфиг или языковой + elseif fileFormat == ".txt" or fileFormat == ".cfg" or fileFormat == ".lang" then + ecs.prepareToExit() + shell.execute("edit "..path) + + --Если это ярлык + elseif fileFormat == ".lnk" then + local shortcutLink = ecs.readShortcut(path) + if fs.exists(shortcutLink) then + launchIcon(shortcutLink) + else + ecs.error(lang.badShortcut) + end + + --Если это ссылка на пастебин + elseif fileFormat == ".paste" then + local shortcutLink = ecs.readShortcut(path) + ecs.prepareToExit() + local success, reason = shell.execute("pastebin run " .. shortcutLink) + if success then + print(lang.programSuccessfullyExecuted) + ecs.waitForTouchOrClick() + else + ecs.displayCompileMessage(1, reason, false) + end + end + + --Ставим старое разрешение + gpu.setResolution(oldWidth, oldHeight) +end + +--Перейти в какую-то папку +local function changePath(path) + table.insert(workPathHistory, workPath) + workPath = path + currentDesktop = 1 + drawDesktop(xPosOfIcons, yPosOfIcons) +end + +--Биометрический сканер +local function biometry() + local users + local path = "System/OS/Users.cfg" + + if fs.exists(path) then + users = config.readFile(path) + + local width = 80 + local height = 25 + + local x, y = math.floor(xSize / 2 - width / 2), math.floor(ySize / 2 - height / 2) + + local Finger = image.load("System/OS/Icons/Finger.png") + local OK = image.load("System/OS/Installer/OK.png") + local OC + + local function okno(color, textColor, text, images) + ecs.square(x, y, width, height, color) + ecs.windowShadow(x, y, width, height) + + image.draw(math.floor(xSize / 2 - 15), y + 2, images) + + gpu.setBackground(color) + gpu.setForeground(textColor) + ecs.centerText("x", y + height - 5, text) + end + + okno(ecs.windowColors.background, ecs.windowColors.usualText, lang.fingerToLogin, Finger) + + local exit + while true do + if exit then break end + + local e = {event.pull()} + if e[1] == "touch" then + for _, val in pairs(users) do + if e[6] == val or e[6] == "IT" then + okno(ecs.windowColors.background, ecs.windowColors.usualText, lang.welcomeBack..e[6], OK) + os.sleep(1.5) + exit = true + break + end + end + + if not exit then + okno(0xaa0000, 0xffffff, lang.accessDenied, Finger) + os.sleep(1.5) + okno(ecs.windowColors.background, ecs.windowColors.usualText, lang.fingerToLogin, Finger) + end + end + end + + Finger = nil + users = nil + end +end + +--Удалить все, что выделено +local function deleteSelectedIcons() + for key, value in pairs(obj["DesktopIcons"]) do + if obj["DesktopIcons"][key][6] ~= nil then + fs.remove(obj["DesktopIcons"][key][5]) + end + end + + drawDesktop(xPosOfIcons, yPosOfIcons) +end + +-- Копирование папки через рекурсию, т.к. fs.copy() не поддерживает папки +-- Ну долбоеб автор мода - хули я тут сделаю? Придется так вот +-- swg2you, привет маме ;) +local function copyFolder(path, toPath) + local function doCopy(path) + local fileList = ecs.getFileList(path) + for i = 1, #fileList do + if fs.isDirectory(path..fileList[i]) then + doCopy(path..fileList[i]) + else + fs.makeDirectory(toPath..path) + fs.copy(path..fileList[i], toPath ..path.. fileList[i]) + end + end + end + + toPath = fs.path(toPath) + doCopy(path.."/") +end + +--Копирование файлов для операционки +local function copy(from, to) + local name = fs.name(from) + local toName = to.."/"..name + local action = ecs.askForReplaceFile(toName) + if action == nil or action == "replace" then + fs.remove(toName) + if fs.isDirectory(from) then + copyFolder(from, toName) + else + fs.copy(from, toName) + end + elseif action == "keepBoth" then + if fs.isDirectory(from) then + copyFolder(from, to .. "/(copy)" .. name) + else + fs.copy(from, to .. "/(copy)" .. name) + end + end +end + +-- Скопировать иконки выделенные +local function copySelectedIcons() + clipboard = {} + for key, value in pairs(obj["DesktopIcons"]) do + if obj["DesktopIcons"][key][6] ~= nil then + table.insert(clipboard, obj["DesktopIcons"][key][5]) + end + end +end + +-- Вставить иконки выделенные +local function pasteSelectedIcons() + for i = 1, #clipboard do + if fs.exists(clipboard[i]) then + copy(clipboard[i], workPath) + else + local action = ECSAPI.select("auto", "auto", " ", {{"Файл \"".. fs.name(clipboard[i]) .. "\" не найден, игнорирую его."}}, {{"Прервать копирование", 0xffffff, 0x000000}, {"Ок"}}) + if action == "Прервать копирование" then break end + end + end + + drawDesktop(xPosOfIcons, yPosOfIcons) + drawDock() +end + +--Запустить конфигуратор ОС, если еще не запускался +local function launchConfigurator() + if not fs.exists("System/OS/Users.cfg") and not fs.exists("System/OS/Password.cfg") and not fs.exists("System/OS/WithoutProtection.cfg") then + drawAll() + --ecs.prepareToExit() + shell.execute("System/OS/Configurator/Configurator.lua") + drawAll() + --ecs.prepareToExit() + return true + end +end + +--Аккуратно запускаем биометрию - а то мало ли ctrl alt c +local function safeBiometry() + ecs.prepareToExit() + while true do + local s, r = pcall(biometry) + if s then break end + end +end + +--Простое окошко ввода пароля и его анализ по конфигу +local function login() + local readedPassword = config.readFile("System/OS/Password.cfg")[1] + while true do + local password = ecs.beautifulInput("auto", "auto", 30, lang.enterSystem, "Ок", ecs.windowColors.background, ecs.windowColors.usualText, 0xcccccc, true, {lang.password, true})[1] + if password == readedPassword then + return + else + ecs.error(lang.accessDenied) + end + end +end + +--Безопасный ввод пароля, чтоб всякие дауны не крашнули прогу +local function safeLogin() + drawAll() + while true do + local s, r = pcall(login) + if s then return true end + end +end + +--Финальный вход в систему +local function enterSystem() + if fs.exists("System/OS/Password.cfg") then + safeLogin() + elseif fs.exists("System/OS/Users.cfg") then + safeBiometry() + drawAll() + elseif fs.exists("System/OS/WithoutProtection.cfg") then + drawAll() + end +end + +--Проверка имени файла для всяких полей ввода, а то заебался писать это везде +local function isNameCorrect(name) + if name ~= "" and name ~= " " and name ~= nil then + return true + else + ecs.error(lang.invalidName) + return false + end +end + +--Рисуем маленькую полоску оповещений +local function notification(text) + local maxWidth = math.floor(xSize * 2 / 3) + local height = 3 + local width = unicode.len(text) + 5 + width = math.min(maxWidth, width) + local x = math.floor(xSize / 2 - width / 2) + local y = 1 + + --Запоминаем, что было нарисовано + local oldPixels = ecs.rememberOldPixels(x, y, x + width - 1, y + height - 1) + + --Рисуем саму полосочку + ecs.square(x, y, width, height, 0xffffff) + ecs.colorText(x + 4, y + 1, ecs.windowColors.usualText, ecs.stringLimit("end", text, width - 5)) + ecs.colorTextWithBack(x + 1, y + 1, 0xffffff, ecs.colors.blue, "❕") + --Крестик + ecs.colorTextWithBack(x + width - 1, y, 0x000000, 0xffffff, "x") + + newObj("Notification", "Exit", x + width - 1, y, x + width - 1, y) + newObj("Notification", "Show", x, y, x + width - 2, y + height - 1) + + return oldPixels +end + + +--А вот и системка стартует +------------------------------------------------------------------------------------------------------------------------ + +if not launchConfigurator() then enterSystem() end + +------------------------------------------------------------------------------------------------------------------------ + +-- Понеслась моча по трубам +while true do + + + local eventData = { event.pull() } + if eventData[1] == "touch" then + + --Удаляем нотификацию, если имеется + if notificationOldPixels then ecs.drawOldPixels(notificationOldPixels); notificationOldPixels = false end + + --Переменная, становящаяся ложью только в случае клика на какой-либо элемент, не суть какой + local clickedOnEmptySpace = true + + --Клик на иконочки раб стола + for key, value in pairs(obj["DesktopIcons"]) do + if ecs.clickedAtArea(eventData[3], eventData[4], obj["DesktopIcons"][key][1], obj["DesktopIcons"][key][2], obj["DesktopIcons"][key][3], obj["DesktopIcons"][key][4]) then + + --Кликнули на элемент, а не в очко какое-то + clickedOnEmptySpace = false + + --ЕСЛИ ЛЕВАЯ КНОПА МЫШИ + if (eventData[5] == 0 and not keyboard.isControlDown()) or (eventData[5] == 1 and keyboard.isControlDown()) then + + --ЕСЛИ НЕ ВЫБРАНА, ТО ВЫБРАТЬ СНАЧАЛА + if not obj["DesktopIcons"][key][6] then + selectIcon(key) + + --А ЕСЛИ ВЫБРАНА УЖЕ, ТО ЗАПУСТИТЬ ПРОЖКУ ИЛИ ОТКРЫТЬ ПАПКУ + else + if fs.isDirectory(obj["DesktopIcons"][key][5]) and ecs.getFileFormat(obj["DesktopIcons"][key][5]) ~= ".app" then + changePath(obj["DesktopIcons"][key][5]) + else + deselectAll(true) + launchIcon(obj["DesktopIcons"][key][5]) + drawAll() + end + end + + --ЕСЛИ ПРАВАЯ КНОПА МЫШИ + elseif eventData[5] == 1 and not keyboard.isControlDown() then + --selectIcon(key) + obj["DesktopIcons"][key][6] = true + redrawSelectedIcons() + + local action + local fileFormat = ecs.getFileFormat(obj["DesktopIcons"][key][5]) + + local function getSelectedIcons() + local selectedIcons = {} + for key, val in pairs(obj["DesktopIcons"]) do + if obj["DesktopIcons"][key][6] then + table.insert(selectedIcons, { ["id"] = key }) + end + end + return selectedIcons + end + + + --РАЗНЫЕ КОНТЕКСТНЫЕ МЕНЮ + if #getSelectedIcons() > 1 then + action = context.menu(eventData[3], eventData[4], {lang.contextCut, false, "^X"}, {lang.contextCopy, false, "^C"}, {lang.contextPaste, not clipboard, "^V"}, "-", {lang.contextArchive, true}, "-", {lang.contextDelete, false, "⌫"}) + elseif fileFormat == ".app" and fs.isDirectory(obj["DesktopIcons"][key][5]) then + action = context.menu(eventData[3], eventData[4], {lang.contextShowContent}, "-", {lang.contextCut, false, "^X"}, {lang.contextCopy, false, "^C"}, {lang.contextPaste, not clipboard, "^V"}, "-", {lang.contextRename}, {lang.contextCreateShortcut}, "-", {lang.contextArchive, true}, {lang.contextUploadToPastebin, true}, "-", {lang.contextAddToDock, not (currentCountOfIconsInDock < dockCountOfIcons and workPath ~= "System/OS/Dock/")}, {lang.contextDelete, false, "⌫"}) + elseif fileFormat ~= ".app" and fs.isDirectory(obj["DesktopIcons"][key][5]) then + action = context.menu(eventData[3], eventData[4], {lang.contextCut, false, "^X"}, {lang.contextCopy, false, "^C"}, {lang.contextPaste, not clipboard, "^V"}, "-", {lang.contextRename}, {lang.contextCreateShortcut}, "-", {lang.contextArchive, true}, {lang.contextUploadToPastebin, true}, "-", {lang.contextDelete, false, "⌫"}) + else + action = context.menu(eventData[3], eventData[4], {lang.contextEdit}, "-", {lang.contextCut, false, "^X"}, {lang.contextCopy, false, "^C"}, {lang.contextPaste, not clipboard, "^V"}, "-", {lang.contextRename}, {lang.contextCreateShortcut}, "-", {lang.contextArchive, true}, {lang.contextUploadToPastebin, true}, "-", {lang.contextAddToDock, not (currentCountOfIconsInDock < dockCountOfIcons and workPath ~= "System/OS/Dock/")}, {lang.contextDelete, false, "⌫"}) + end + + --ecs.error(#getSelectedIcons()) + deselectAll() + --ecs.error(#getSelectedIcons()) + + --ecs.error("workPath = "..workPath..", obj = "..obj["DesktopIcons"][key][5]) + + if action == lang.contextShowContent then + changePath(obj["DesktopIcons"][key][5]) + elseif action == lang.contextEdit then + ecs.prepareToExit() + shell.execute("edit "..obj["DesktopIcons"][key][5]) + drawAll() + elseif action == lang.contextDelete then + deleteSelectedIcons() + elseif action == lang.contextCopy then + copySelectedIcons() + elseif action == lang.contextPaste then + pasteSelectedIcons() + elseif action == lang.contextRename then + local success = ecs.rename(obj["DesktopIcons"][key][5]) + success = true + if success then drawDesktop(xPosOfIcons, yPosOfIcons) end + drawDesktop(xPosOfIcons, yPosOfIcons) + elseif action == lang.contextCreateShortcut then + createShortCut(workPath .. ecs.hideFileFormat(obj["DesktopIcons"][key][5]) .. ".lnk", obj["DesktopIcons"][key][5]) + drawDesktop(xPosOfIcons, yPosOfIcons) + elseif action == lang.contextAddToDock then + createShortCut("System/OS/Dock/" .. ecs.hideFileFormat(obj["DesktopIcons"][key][5]) .. ".lnk", obj["DesktopIcons"][key][5]) + drawDock() + else + redrawSelectedIcons() + deselectAll(true) + end + + end + + break + end + end + + --ПРОСЧЕТ КЛИКА НА КНОПОЧКИ ПЕРЕКЛЮЧЕНИЯ РАБОЧИХ СТОЛОВ + for key, value in pairs(obj["DesktopButtons"]) do + if ecs.clickedAtArea(eventData[3], eventData[4], obj["DesktopButtons"][key][1], obj["DesktopButtons"][key][2], obj["DesktopButtons"][key][3], obj["DesktopButtons"][key][4]) then + + --Кликнули на элемент, а не в очко какое-то + clickedOnEmptySpace = false + + if key == 0 then + if #workPathHistory > 0 then + ecs.colorTextWithBack(obj["DesktopButtons"][key][1], obj["DesktopButtons"][key][2], 0xffffff, ecs.colors.green, " <") + os.sleep(0.2) + workPath = workPathHistory[#workPathHistory] + workPathHistory[#workPathHistory] = nil + currentDesktop = 1 + + drawDesktop(xPosOfIcons, yPosOfIcons) + end + else + currentDesktop = key + drawDesktop(xPosOfIcons, yPosOfIcons) + end + + break + end + end + + --Клик на Доковские иконки + for key, value in pairs(obj["DockIcons"]) do + if ecs.clickedAtArea(eventData[3], eventData[4], obj["DockIcons"][key][1], obj["DockIcons"][key][2], obj["DockIcons"][key][3], obj["DockIcons"][key][4]) then + + --Кликнули на элемент, а не в очко какое-то + clickedOnEmptySpace = false + + ecs.square(obj["DockIcons"][key][1], obj["DockIcons"][key][2], widthOfIcon, heightOfIcon, iconsSelectionColor) + ecs.drawOSIcon(obj["DockIcons"][key][1] + 2, obj["DockIcons"][key][2], pathOfDockShortcuts..key, showFileFormat) + + if eventData[5] == 0 then + os.sleep(0.2) + launchIcon(pathOfDockShortcuts..key) + drawAll() + else + local content = ecs.readShortcut(pathOfDockShortcuts..key) + + action = context.menu(eventData[3], eventData[4], {lang.contextOpenDockFolder}, {lang.contextOpenDockElementFolder, (fs.path(workPath) == fs.path(content))}, "-", {lang.contextRemoveFromDock, not (currentCountOfIconsInDock > 1)}) + + if action == lang.contextOpenDockElementFolder then + drawDock() + if content then + changePath(fs.path(content)) + end + elseif action == lang.contextRemoveFromDock then + fs.remove(pathOfDockShortcuts..key) + drawDock() + elseif action == lang.contextOpenDockFolder then + drawDock() + changePath(pathOfDockShortcuts) + else + drawDock() + end + + break + + end + end + end + + --Обработка верхних кнопок - ну, вид там, и проч + for key, val in pairs(obj["TopBarButtons"]) do + if ecs.clickedAtArea(eventData[3], eventData[4], obj["TopBarButtons"][key][1], obj["TopBarButtons"][key][2], obj["TopBarButtons"][key][3], obj["TopBarButtons"][key][4]) then + + --Кликнули на элемент, а не в очко какое-то + clickedOnEmptySpace = false + + ecs.colorTextWithBack(obj["TopBarButtons"][key][1], obj["TopBarButtons"][key][2], 0xffffff, ecs.colors.blue, " "..key.." ") + + if key == lang.viewTab then + + local action = context.menu(obj["TopBarButtons"][key][1], obj["TopBarButtons"][key][2] + 1, {(function() if showHiddenFiles then return lang.hideHiddenFiles else return lang.showHiddenFiles end end)()}, {(function() if showSystemFiles then return lang.hideSystemFiles else return lang.showSystemFiles end end)()}, "-", {(function() if showFileFormat then return lang.hideFileFormat else return lang.showFileFormat end end)()}) + + if action == lang.hideHiddenFiles then + showHiddenFiles = false + elseif action == lang.showHiddenFiles then + showHiddenFiles = true + elseif action == lang.showSystemFiles then + showSystemFiles = true + elseif action == lang.hideSystemFiles then + showSystemFiles = false + elseif action == lang.showFileFormat then + showFileFormat = true + elseif action == lang.hideFileFormat then + showFileFormat = false + end + + drawTopBar() + drawDesktop(xPosOfIcons, yPosOfIcons) + + elseif key == "MineOS" then + local action = context.menu(obj["TopBarButtons"][key][1], obj["TopBarButtons"][key][2] + 1, {lang.aboutSystem}, {lang.updateSystem}, "-", {lang.restart}, {lang.shutdown}, "-", {lang.backToShell}) + + if action == lang.backToShell then + ecs.prepareToExit() + return 0 + elseif action == lang.shutdown then + shell.execute("shutdown") + elseif action == lang.restart then + shell.execute("reboot") + elseif action == lang.updateSystem then + shell.execute("pastebin run 0nm5b1ju") + ecs.prepareToExit() + return 0 + elseif action == lang.aboutSystem then + ecs.prepareToExit() + print(copyright) + print(" А теперь жмякай любую кнопку и продолжай работу с ОС.") + ecs.waitForTouchOrClick() + drawAll() + end + end + + drawTopBar() + + break + + end + end + + --А если все-таки кликнулось в очко какое-то, то вот че делать + if clickedOnEmptySpace then + if eventData[5] == 1 then + local action = context.menu(eventData[3], eventData[4], {lang.contextNewFile}, {lang.contextNewFolder}, "-", {lang.contextPaste, not clipboard, "^V"}, {lang.contextRunFromPastebin}, {lang.contextCreatePastebinShortcut}) + + --Создать новый файл + if action == lang.contextNewFile then + local name = ecs.beautifulInput("auto", "auto", 30, lang.contextNewFile, "Ок", ecs.windowColors.background, ecs.windowColors.usualText, 0xcccccc, true, {lang.name})[1] + if isNameCorrect(name) then + ecs.prepareToExit() + shell.execute("edit " .. workPath .. name) + drawAll() + end + + --Создать новую папку + elseif action == lang.contextNewFolder then + local name = ecs.beautifulInput("auto", "auto", 30, lang.contextNewFolder, "Ок", ecs.windowColors.background, ecs.windowColors.usualText, 0xcccccc, true, {lang.name})[1] + if isNameCorrect(name) then + fs.makeDirectory(workPath .. name) + drawDesktop(xPosOfIcons, yPosOfIcons) + end + + --Запустить файл из пастебина + elseif action == lang.contextRunFromPastebin then + local name = ecs.beautifulInput("auto", "auto", 30, lang.contextRunFromPastebin, "Ок", ecs.windowColors.background, ecs.windowColors.usualText, 0xcccccc, true, {lang.name})[1] + if isNameCorrect(name) then + ecs.prepareToExit() + shell.execute("pastebin run "..name) + print(" "); print(" ") + print(lang.pressAnyKeyToContinue) + ecs.waitForTouchOrClick() + drawAll() + end + + --Создать ссылку на файл из пастебина + elseif action == lang.contextCreatePastebinShortcut then + local name = ecs.beautifulInput("auto", "auto", 30, lang.contextCreatePastebinShortcut, "Ок", ecs.windowColors.background, ecs.windowColors.usualText, 0xcccccc, true, {lang.name})[1] + if isNameCorrect(name) then + createPastebinShortcut(workPath, name) + drawDesktop(xPosOfIcons, yPosOfIcons) + end + + --Вставить файл + elseif action == lang.contextPaste then + pasteSelectedIcons() + end + end + end + + + --ПРОКРУТКА РАБОЧИХ СТОЛОВ + elseif eventData[1] == "scroll" then + if eventData[5] == -1 then + if currentDesktop > 1 then currentDesktop = currentDesktop - 1; drawDesktop(xPosOfIcons, yPosOfIcons) end + else + if currentDesktop < countOfDesktops then currentDesktop = currentDesktop + 1; drawDesktop(xPosOfIcons, yPosOfIcons) end + end + + --Если скрин делаем + elseif eventData[1] == "screenshot" then + drawDesktop(xPosOfIcons, yPosOfIcons) + + --Сочетания клавищ, пока не реализовано + elseif eventData[1] == "key_down" then + + end +end + + + + + + + + ----------------------------------------------------------------------------------------------------- -return ECSAPI