CCCPaste

Context API

function menu(...)
        --ЕСЛИ ЧИСЛО АРУМЕНТОВ < 3 И ТИП ТРЕТЬЕГО АРГУМЕНТА НЕ TABLE, ТО ВЫДАТЬ ОШИБКУ ПО ИСПОЛЬЗОВАНИЮ API
        if #arg < 3 or type(arg[3]) ~= "table" then error("Usage: menu(number x,number y,table Element1,table Element2, table Element3...) \nReturns: string Action \n structure: {string Name[, boolean isElementHidden][,number colorOfText]}") end
       
        --ПОЛУЧЕНИЕ РАЗМЕРА МОНИТОРА
        local xSize, ySize = term.getSize()
 
        --ПРОСТОЕ ОТОБРАЖЕНИЕ ТЕКСТА В УКАЗАННЫХ КООРДИНАТАХ С УКАЗАННЫМ ЦВЕТОМ
        local function text(x,y,text1,color)
                term.setTextColor(color)
                term.setCursorPos(x,y)
                term.write(text1)
        end
 
        --СОЗДАНИЕ ОБЪЕКТОВ В ПАМЯТИ (В НАШЕМ СЛУЧАЕ КНОПОК, ОТВЕЧАЮЩИХ ЗА ВЫБОР ЭЛЕМЕНТА МЕНЮ)
        local Objects = {}
        local function newObj(name,isHidden,xStart,xEnd,y)
                Objects[name]={}
                Objects[name]["isHidden"] = isHidden
                Objects[name]["xStart"] = xStart
                Objects[name]["xEnd"] = xEnd
                Objects[name]["y"] = y
        end
       
        --ОПРЕДЕЛЕНИЕ САМОГО ДЛИННОГО ПО КОЛ-ВУ СИМВОЛОВ ЭЛЕМЕНТА МЕНЮ
        local theLongestElement = #arg[3][1]
        for i=3,#arg do
                if arg[i] ~= "-" and theLongestElement < #arg[i][1] then
                        theLongestElement = #arg[i][1]
                end
        end
 
        --ОПРЕДЕЛЕНИЕ РАЗМЕРА МЕНЮ
        local xSizeOfMenu = theLongestElement + 4
        local ySizeOfMenu = #arg-2
 
        local xStartToDisplay = nil
        local yStartToDisplay = nil
 
        --РИСОВАНИЕ КВАДРАТА С ЗАЛИВКОЙ
        local function square(x1,y1,width,height,color)
                local string = string.rep(" ",width)
                term.setBackgroundColor(color)
                for y=y1,(y1+height-1) do
                        term.setCursorPos(x1,y)
                        term.write(string)
                end
        end
 
        --ОТРИСОВКА РАЗДЕЛИТЕЛЯ В МЕНЮ
        local function drawSeparator(x,y,size)
                term.setTextColor(colors.lightGray)
                term.setCursorPos(x,y)
                term.write(string.rep("-",size))
        end
       
        --ФУНКЦИЯ ОТРИСОВКИ ВСЕГО МЕНЮ
        local function drawMenu(xMenu,yMenu)
 
                --КОРРЕКЦИЯ КООРДИНАТЫ МЕНЮ, ЧТОБ ЗА КРАЯ ЭКРАНА НЕ ЗАЛЕЗАЛО
                if yMenu+ySizeOfMenu - 1  >= ySize then yMenu = yMenu - (yMenu+ySizeOfMenu - 1 - ySize) - 1 end
                if xMenu+xSizeOfMenu - 1  >= xSize then xMenu = xMenu - (xMenu+xSizeOfMenu - 1 - xSize) - 1 end
 
                --ОПРЕДЕЛЕНИЕ ТОЧЕК СТАРТА ОТОБРАЖЕНИЯ ТЕКСТА В МЕНЮ
                xStartToDisplay = xMenu + 2
                yStartToDisplay = yMenu
 
                --ОТРИСОВКА ТЕНИ МЕНЮ
                square(xMenu+1,yMenu+1,xSizeOfMenu,ySizeOfMenu,colors.gray)
 
                --ОТРИСОВКА БЕЛОЙ ПОДЛОЖКИ МЕНЮ
                square(xMenu,yMenu,xSizeOfMenu,ySizeOfMenu,colors.white)
 
                --ЦИКЛ ПЕРЕБОРА ВСЕХ ЭЛЕМЕНТОВ МЕНЮ, РАССМАТРИВАЕМ ДАННЫЕ О КАЖДОМ
                for i=3,#arg do
                        --ЕСЛИ ВЫБРАННЫХ ЭЛЕМЕНТ НЕ ЯВЛЯЕТСЯ РАЗДЕЛИТЕЛЕМ, ТО
                        if arg[i] ~= "-" then
                                --ЗАДАНИЕ СТАНДАРТНОГО ЦВЕТА ТЕКСТА ДЛЯ ЭЛЕМЕНТА МЕНЮ
                                local contextColor = colors.black
                                --ЕСЛИ АРГУМЕНТ_2 (СКРЫТЫЙ/НЕ СКРЫТЫЙ) И АРУМЕНТ_3 (ЦВЕТ ТЕКСТА ЭЛЕМЕНТА) ДЛЯ РАССМАТРИВАЕМОГО ЭЛЕМЕНТА НЕ УКАЗАНЫ, ТО
                                if arg[i][2] == nil and arg[i][3] == nil then
                                        contextColor = colors.black
                                --ЕСЛИ АРГУМЕНТ 2 = FALSE И АРГУМЕНТ 3 НЕ УКАЗАН, ТО
                                elseif arg[i][2] == false and arg[i][3] == nil then
                                        contextColor = colors.black
                                --ЕСЛИ АРГУМЕНТ 2 = FALSE И АРГУМЕНТ 3 УКАЗАН, ТО
                                elseif arg[i][2] == false and arg[i][3] ~= nil then
                                        contextColor = arg[i][3]
                                --ЕСЛИ АРГУМЕНТ 2 = TRUE, ТО ЭЛЕМЕНТ СКРЫТ
                                elseif arg[i][2] == true then
                                        contextColor = colors.lightGray
                                end
 
                                --ОТОБРАЖЕНИЕ ТЕКСТА ЭЛЕМЕНТА В САМОМ МЕНЮ
                                text(xStartToDisplay,yStartToDisplay+i-3,arg[i][1],contextColor)
                                --СОЗДАНИЕ ОБЪЕКТА ЭЛЕМЕНТА В ПАМЯТИ, ЧТОБЫ ПОТОМ ИМЕТЬ К НЕМУ ДОСТУП
                                newObj(arg[i][1],arg[i][2],xMenu,xMenu+xSizeOfMenu-1,yStartToDisplay+i-3)
 
                        --А ЕСЛИ ВСЕ-ТАКИ ЯВЛЯЕТСЯ, ТО
                        else
                                drawSeparator(xMenu,yStartToDisplay+i-3,xSizeOfMenu)
                        end
                end
        end
       
        --СТАРТ ПРОГРАММЫ, РИСУЕМ МЕНЮ
        drawMenu(arg[1],arg[2])
 
        --ОТСЛЕЖИВАНИЕ КЛИКА МЫШИ
        local event,side,xClick,yClick = os.pullEvent()
        if event == "monitor_touch" then side = 1 end
        if event == "mouse_click" or event == "monitor_touch" then
                --ПЕРЕБОР ВСЕХ ЭЛЕМЕНТОВ МАССИВА ОБЪЕКТОВ В ПАРЕ СО ЗНАЧЕНИЕМ ЭЛЕМЕНТА (КЛЮЧ = ЗНАЧЕНИЕ, KEY = VAL)
                for key,val in pairs(Objects) do
                        --ЕСЛИ МЫ КЛИКНУЛИ НА ОБЪЕКТ, И ЭТОТ ОБЪЕКТ НЕ ЯВЛЯЕТСЯ СКРЫТЫМ, ТО
                        if xClick >= Objects[key]["xStart"] and xClick <= Objects[key]["xEnd"] and yClick == Objects[key]["y"] and Objects[key]["isHidden"] == false or xClick >= Objects[key]["xStart"] and xClick <= Objects[key]["xEnd"] and yClick == Objects[key]["y"] and Objects[key]["isHidden"] == nil then
                                --НАРИСОВАТЬ ГОЛУБОЕ ВЫДЕЛЕНИЕ ЭЛЕМЕНТА МЕНЮ
                                for i=Objects[key]["xStart"],Objects[key]["xEnd"] do
                                        paintutils.drawPixel(i,Objects[key]["y"],colors.blue)
                                end
                                --ОТОБРАЗИТЬ ТОТ ЖЕ ТЕКСТ, ТОЛЬКО БЕЛЫМ ЦВЕТОМ
                                text(xStartToDisplay,Objects[key]["y"],key,colors.white)
                                --ЖДАТЬ НЕКОТОРОЕ ВРЕМЯ
                                sleep(0.3)
                                --ВЕРНУТЬ ЗНАЧЕНИЕ KEY (ТО ЕСТЬ ЗНАЧЕНИЕ ВЫБРАННОГО ЭЛЕМЕНТА МЕНЮ) И ЗАВЕШИТЬ ПРОГРАММУ МЕНЮ
                                return key
                        end
                        --А ЕСЛИ НИКАКОЙ ЭЛЕМЕНТ МЕНЮ НЕ БЫЛ ВЫБРАН, ТО ФУНКЦИЯ ВЕРНЕТ NIL
                end
        end
end