Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- Touch API v0.5.0.1
- --
- -- Requirements:
- -- Make sure enableAPI_http=true in ComputerCraft.cfg
- -- Any computer or turtle
- -- Advanced monitor at any side
- --
- local saveFile = "touch.save"
- local debugMode, sideMonitor, noMonitor, canSave
- local buttons, debugInfo, titleData, waitForFuncs = {}, {}, {}, {}
- local defaultColors = {colors.white, colors.black}
- local defaultButtonColors = {colors.lime, colors.black, colors.gray, colors.white}
- local defaultPopupColors = {colors.white, colors.black, colors.lightGray}
- args = function (...)
- local args = {...}
- if type(args[1]) == "table" then args = args[1] end
- return args
- end
- dbg = function (...)
- if #{...} > 0 then
- if debugMode then
- if term.isColor() then term.setTextColor(colors.lime) end
- print("DBG: ", ...)
- if term.isColor() then term.setTextColor(colors.white) end
- else
- table.insert(debugInfo, {...})
- end
- else
- debugMode = not debugMode
- if debugMode then
- for k, v in pairs(debugInfo) do dbg(unpack(v)) end
- debugInfo = {}
- dbg("Debug mode enabled.")
- else
- dbg("Debug mode disabled.")
- end
- end
- return true
- end
- err = function (...)
- if term.isColor() then term.setTextColor(colors.red) end
- print("ERR: ", ...)
- if term.isColor() then term.setTextColor(colors.white) end
- return false
- end
- checkText = function (text)
- if type(text) == "string" then return true end
- if type(text) == "table" then
- local result = true
- for k, v in pairs(text) do
- result = result and checkText(v)
- end
- return result
- end
- return false
- end
- checkColor = function (color)
- if type(color) == "number" then
- if color >= 0 and color < 2^16 then
- return true
- end
- end
- return false
- end
- setDefaultColors = function (...)
- dbg("Changing default colors.")
- for k, v in pairs(args(...)) do
- if checkColor(v) then
- defaultButtonColors[k] = v
- end
- end
- end
- setMonitorSide = function (side)
- if peripheral.getType(side) == "monitor" then
- sideMonitor = side
- return dbg("Connected to monitor. (", side, ")")
- end
- return err("No monitor on \"", side, "\" side.")
- end
- setMonitor = function (side)
- local validSide = false
- for k, v in pairs(rs.getSides()) do
- if v == side then
- validSide = true
- break
- end
- end
- if validSide then
- return setMonitorSide(side)
- else
- return err("Wrong side.")
- end
- end
- detectMonitor = function ()
- for k, v in pairs(rs.getSides()) do
- if peripheral.getType(v) == "monitor" then
- return setMonitorSide(v)
- end
- end
- return err("Can't find the monitor.")
- end
- monitor = function (method, ...)
- if not sideMonitor then
- if noMonitor then return false end
- dbg("Trying to detect monitor.")
- if not detectMonitor() then
- noMonitor = true
- return false
- end
- end
- return peripheral.call(sideMonitor, method, ...)
- end
- getID = function (value)
- if type(value) == "string" then
- for id, data in pairs(buttons) do
- if value == data.text then return id end
- end
- elseif type(value) == "number" then
- if buttons[value] then return value end
- end
- return false
- end
- getData = function (button)
- local id = getID(button)
- if id then
- return id, buttons[id]
- end
- return false
- end
- getAllData = function ()
- return buttons
- end
- addButton = function (text, func, coord, ...)
- if type(text) == "number" then text = tostring(text) end
- if not checkText(text) then return err("Wrong text type.") end
- if type(coord[1]) ~= "number" or type(coord[2]) ~= "number" then
- return err("Wrong coordinates.")
- end
- --dbg("Adding button: \"", text, "\" (ID: ", #buttons+1, ")")
- local W, H = getTextSize(text)
- if type(coord[3]) ~= "number" then coord[3] = W end
- if type(coord[4]) ~= "number" then coord[4] = H end
- local color = args(...)
- for k, v in pairs(defaultButtonColors) do
- if not checkColor(color[k]) then color[k] = v end
- end
- local button = {
- ["active"] = false,
- ["text"] = text,
- ["func"] = func,
- ["coord"] = {
- ["X"] = coord[1],
- ["Y"] = coord[2],
- ["W"] = coord[3],
- ["H"] = coord[4],
- },
- ["color"] = {
- ["B"] = color[1],
- ["T"] = color[2],
- ["b"] = color[3],
- ["t"] = color[4],
- },
- }
- table.insert(buttons, button)
- return #buttons, button
- end
- deleteButton = function (...)
- local arr = args(...)
- if #arr < 1 then
- dbg("Removing all buttons.")
- buttons = {}
- return true
- end
- for k, v in pairs(arr) do
- local id, data = getData(v)
- if id then
- --dbg("Removing button: \"", data.text, "\" (ID: ", id, ")")
- table.remove(buttons, id)
- end
- end
- return true
- end
- executeFunction = function (button)
- local id, data = getData(button)
- if id then
- if type(data.func) == "function" then
- dbg("Executing function. (ID: ", id, ")")
- return data.func(id, data)
- end
- end
- end
- simulateTouch = function (...)
- for k, v in pairs(args(...)) do
- sleep(0)
- executeFunction(v)
- end
- end
- forEach = function (func)
- for id, data in pairs(buttons) do
- if type(func) == "function" then
- func(id, data)
- else
- executeFunction(id)
- end
- end
- end
- enableButton = function (...)
- local arr = args(...)
- if #arr < 1 then
- dbg("Enabling all buttons.")
- for id, data in pairs(buttons) do
- enableButton(id)
- end
- return true
- end
- for k, v in pairs(arr) do
- local id, data = getData(v)
- if id and not data.active then
- --dbg("Changing \"", data.text, "\": ", data.active, " -> ", true)
- data.active = true
- drawButton(id)
- end
- end
- return true
- end
- disableButton = function (...)
- local arr = args(...)
- if #arr < 1 then
- dbg("Disabling all buttons.")
- for id, data in pairs(buttons) do
- disableButton(id)
- end
- return true
- end
- for k, v in pairs(arr) do
- local id, data = getData(v)
- if id and data.active then
- --dbg("Changing \"", data.text, "\": ", data.active, " -> ", false)
- data.active = false
- drawButton(id)
- end
- end
- return true
- end
- toggleButton = function (...)
- local arr = args(...)
- if #arr < 1 then
- dbg("Toggling all buttons.")
- for id, data in pairs(buttons) do
- toggleButton(id)
- end
- return true
- end
- for k, v in pairs(arr) do
- local id, data = getData(v)
- if id then
- --dbg("Changing \"", data.text, "\": ", data.active, " -> ", not data.active)
- data.active = not data.active
- drawButton(id)
- end
- end
- return true
- end
- blinkButton = function (button, delay)
- if type(delay) ~= "number" then delay = 0.5 end
- local id, data = getData(button)
- if id then
- dbg("Blinking \"", data.text, "\" for ", delay, " sec.")
- toggleButton(id)
- sleep(delay)
- toggleButton(id)
- return true
- end
- return false
- end
- setColor1 = function (color)
- if type(color) ~= "number" then color = defaultColors[1] end
- --dbg("Set text color to: ", color)
- monitor("setTextColor", color)
- end
- setColor2 = function (color)
- if type(color) ~= "number" then color = defaultColors[2] end
- --dbg("Set background color to: ", color)
- monitor("setBackgroundColor", color)
- end
- setColors = function (color1, color2)
- setColor1(color1)
- setColor2(color2)
- end
- getTextSize = function (text)
- if not checkText(text) then return false end
- if type(text) ~= "table" then text = {text} end
- local len = {}
- for k, v in pairs(text) do len[k] = string.len(v) end
- return math.max(unpack(len)), #text
- end
- drawText = function (X, Y, text, color)
- if not X or not Y then return err("Expected X and Y.") end
- if not text then text = " " end
- if type(text) == "string" then
- if string.len(text) > 1 then X = X-string.len(text)/2 end
- if checkColor(color) then setColor1(color) end
- monitor("setCursorPos", math.floor(X), math.floor(Y))
- monitor("write", text)
- if checkColor(color) then setColor1(color) end
- return true
- elseif type(text) == "table" and checkText(text) then
- for k, v in pairs(text) do
- drawText(X, Y-#text/2+k-1, v, color)
- end
- return true
- else
- return err("Wrong text type.")
- end
- end
- setTitle = function (text, color)
- if type(text) == "string" then titleData[1] = text end
- if checkColor(color) then titleData[2] = color end
- return drawTitle()
- end
- drawTitle = function ()
- text, color = unpack(titleData)
- if not text then return false end
- dbg("Drawing title.")
- return drawText(monitor("getSize")/2+1, 1, text, color)
- end
- drawRectangle = function (X1, Y1, X2, Y2, color)
- if color then setColor2(color) end
- for Y = 0, Y2-Y1 do
- if Y == 0 or Y == Y2-Y1 then
- for X = 0, X2-X1 do
- drawText(X1+X, Y1+Y)
- end
- else
- drawText(X1, Y1+Y)
- drawText(X2, Y1+Y)
- end
- end
- if color then setColor2() end
- end
- drawFilledRectangle = function (X1, Y1, X2, Y2, color)
- if color then setColor2(color) end
- for Y = 0, Y2-Y1 do
- for X = 0, X2-X1 do
- drawText(X1+X, Y1+Y)
- end
- end
- if color then setColor2() end
- end
- drawButton = function (button)
- local id, data = getData(button)
- if id then
- --dbg("Drawing button: \"", data.text, "\"")
- if data.active then
- setColors(data.color.T, data.color.B)
- else
- setColors(data.color.t, data.color.b)
- end
- local X, Y = data.coord.X, data.coord.Y
- local W, H = data.coord.W, data.coord.H
- drawFilledRectangle(X, Y, X+W, Y+H)
- drawText(X+W/2, Y+H/2, data.text)
- setColors()
- return true
- elseif not button then
- dbg("Drawing buttons.")
- for id, data in pairs(buttons) do
- drawButton(id)
- end
- return true
- end
- return err("Wrong button. Can't draw.")
- end
- drawPopup = function (text, ...)
- if not checkText(text) then return err("Wrong text. Can't draw popup.") end
- dbg("Drawing popup.")
- local color = args(...)
- if color[1] and not color[3] then color[3] = color[1] end
- for k, v in pairs(defaultPopupColors) do
- if not checkColor(color[k]) then color[k] = v end
- end
- local mW, mH = monitor("getSize")
- local tW, tH = getTextSize(text)
- local X, Y = math.floor((mW-tW)/2), math.floor((mH-tH)/2)
- drawRectangle (X+1-2, Y+1-2, X+tW+2, Y+tH+2, color[3])
- drawFilledRectangle(X+1-1, Y+1-1, X+tW+1, Y+tH+1, color[2])
- setColors(color[1], color[2])
- drawText(X+1+tW/2, Y+1+tH/2, text)
- setColors()
- return true
- end
- whatButtonIs = function (X, Y)
- for id, data in pairs(buttons) do
- if X >= data.coord.X and X < data.coord.X + data.coord.W then
- if Y >= data.coord.Y and Y < data.coord.Y + data.coord.H then
- return id, data
- end
- end
- end
- return false
- end
- waitForTouch = function ()
- dbg("Waiting for touch.")
- local event, side, X, Y = os.pullEvent("monitor_touch")
- dbg("Touch: ", X, "*", Y)
- return X, Y
- end
- waitForButton = function (button)
- local waitID = getID(button)
- while true do
- local X, Y = waitForTouch()
- local id, data = whatButtonIs(X, Y)
- if id then
- dbg("Detected button: \"", data.text, "\" (ID: ", id, ")")
- if not waitID or id == waitID then
- executeFunction(id)
- return id, data
- end
- end
- end
- end
- waitReboot = function ()
- for k, v in pairs(rs.getSides()) do
- if rednet.isOpen(v) then break end
- if peripheral.getType(v) == "modem" then rednet.open(v) end
- end
- while true do
- local event, id, text = os.pullEvent("rednet_message")
- if text == "reboot" then os.reboot() end
- end
- return true
- end
- waitFor = function (...)
- local funcs = {}
- for k, v in pairs(args(...)) do
- if type(v) == "function" then
- table.insert(funcs, v)
- end
- end
- waitForFuncs = funcs
- end
- waitForAny = function (...)
- local funcs = {}
- for k, v in pairs({unpack(waitForFuncs), unpack(args(...))}) do
- if type(v) == "function" then
- table.insert(funcs, function() v() return true end)
- elseif type(v) == "number" then
- table.insert(funcs, function() sleep(v) return true end)
- end
- end
- table.insert(funcs, waitReboot)
- parallel.waitForAny(unpack(funcs))
- return X, Y
- end
- touchOrAny = function (...)
- local X, Y
- waitForAny(function() X, Y = waitForTouch() end, ...)
- return X, Y
- end
- buttonOrAny = function (...)
- local id, data
- waitForAny(function() id, data = waitForButton() end, ...)
- return id, data
- end
- clear = function ()
- dbg("Clearing.")
- setColors()
- monitor("clear")
- monitor("setCursorPos", 1, 1)
- return true
- end
- redraw = function (delay)
- if type(delay) == "number" then
- touchOrAny(delay)
- end
- dbg("Redrawing.")
- clear()
- drawTitle()
- drawButton()
- return true
- end
- prepare = function (...)
- drawButton()
- simulateTouch(...)
- canSave = true
- end
- run = function (...)
- prepare(...)
- dbg("Starting main processing cycle.")
- while true do
- buttonOrAny()
- end
- end
- save = function ()
- if not canSave then return false end
- dbg("Saving to \"", saveFile, "\".")
- local f = fs.open(saveFile, "w")
- if f then
- for id, data in pairs(buttons) do
- if data.active then
- f.writeLine(tostring(id))
- end
- end
- return f.close()
- end
- return err("Cannot save.")
- end
- load = function ()
- dbg("Loading from \"", saveFile, "\".")
- local f, t = fs.open(saveFile, "r"), {}
- if f then
- while true do
- local s = f.readLine()
- if not s then break end
- table.insert(t, tonumber(s))
- end
- f.close()
- return t
- end
- return false
- end
- default = setDefaultColors
- color = setDefaultColors
- set = setMonitor
- title = setTitle
- all = getAllData
- data = getData
- add = addButton
- del = deleteButton
- delete = deleteButton
- enable = enableButton
- on = enableButton
- disable = disableButton
- off = disableButton
- toggle = toggleButton
- blink = blinkButton
- draw = drawButton
- popup = drawPopup
- simulate = simulateTouch
- touch = simulateTouch
- wait = waitFor
- touchOr = touchOrAny
- buttonOr = buttonOrAny
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement