Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local args = {...}
- local file_name = args[1] or nil
- local tw, th = term.getSize()
- local gui_objs
- local gui_menu = "default"
- local preview = false
- local function w(obj)
- return obj.a - obj.x + 1
- end
- local function h(obj)
- return obj.b - obj.y + 1
- end
- function twrite(str) -- From the Googol API
- local tbl = {}
- for char in string.gmatch(str, ".") do
- table.insert(tbl, char)
- end
- local skip = false
- for i=1, #tbl do
- if tbl[i] == "&" then
- if string.match(tbl[i+1], "%x") then
- skip = true
- term.setTextColor(2^tonumber(tbl[i+1], 16))
- else
- write("&")
- end
- elseif tbl[i] == "#" then
- if string.match(tbl[i+1], "%x") then
- skip = true
- term.setBackgroundColor(2^tonumber(tbl[i+1], 16))
- else
- write("#")
- end
- elseif not skip then
- write(tbl[i])
- else
- skip = false
- end
- end
- --term.setTextColor(colors.white)
- end
- function tlen(str)
- local len = 0
- local tbl = {}
- for char in string.gmatch(str, ".") do
- table.insert(tbl, char)
- end
- local skip = false
- for i=1, #tbl do
- if tbl[i] == "&" then
- if string.match(tbl[i+1], "%x") then
- skip = true
- else
- len = len + 1
- end
- elseif tbl[i] == "#" then
- if string.match(tbl[i+1], "%x") then
- skip = true
- else
- len = len + 1
- end
- elseif not skip then
- len = len + 1
- else
- skip = false
- end
- end
- return len
- end
- local function newObject(x, y, a, b, bc, tc, menu)
- if not menu then menu = gui_menu end
- local obj = {x=x, y=y, a=a, b=b, bc=bc, tc=tc}
- local i = #gui_objs[menu] + 1
- gui_objs[menu][i] = obj
- return i
- end
- local function newImage(x, y, data)
- local w = 0
- for ind,val in pairs(data) do
- for i = #val, 1, -1 do
- if val[i] == 0 then
- data[ind][i] = nil
- else
- break
- end
- end
- w = (#val > w and #val) or w
- end
- for i = #data, 1, -1 do
- if #data[i] == 0 then
- data[i] = nil
- else
- break
- end
- end
- local h = #data
- local i = #gui_objs[gui_menu] + 1
- gui_objs[gui_menu][i] = {x=x, y=y, a=x+w, b=y+h, d=data, nfp=1}
- return i
- end
- local function wordwrap(text, w)
- local lines = {} -- stores all the lines
- for match in string.gmatch(text, "[^\n]+") do -- seperate the block of text into seperate lines
- local len = 0
- local line = ""
- for word in string.gmatch(match, "[^%s]+") do -- word wrap if the line is too long
- word = word .. " "
- if tlen(line..word) > w then
- table.insert(lines, line)
- line = ""
- end
- line = line .. word
- while tlen(line) > w do
- table.insert(lines, line:sub(1, w))
- line = line:sub(w+1)
- end
- end
- table.insert(lines, line)
- end
- local delete = {}
- for i,v in pairs(lines) do
- lines[i] = v:match("^%s*(.-)%s*$")
- if lines[i] == "" then
- table.insert(delete, i)
- end
- end
- for i,v in pairs(delete) do lines[v] = nil end
- return lines
- end
- local function drawGui()
- for i,v in pairs(gui_objs[gui_menu]) do
- if not v.nfp then
- term.setBackgroundColor(v.bc)
- term.setTextColor(v.tc)
- for y = v.y, v.b do
- term.setCursorPos(v.x, y)
- term.write(string.rep(" ", w(v)))
- end
- if v.t then
- v.t = v.t:match("^%s*(.+)%s*$") or v.t
- local lines = wordwrap(v.t, w(v) - 2)
- for i2,line in pairs(lines) do
- term.setCursorPos(v.x + math.floor(w(v)/2-tlen(line)/2), v.y + h(v)/2 - #lines/2 + i2 - 1) -- ((h(v)%2==1 and h(v)/2) or ((h(v)/2)-1))
- twrite(line)
- end
- end
- if not preview then
- if v.bc == colors.lightGray then
- term.setTextColor(colors.gray)
- else
- term.setTextColor(colors.lightGray)
- end
- term.setCursorPos(v.x, v.y)
- term.write("+")
- term.setCursorPos(v.a, v.b)
- term.write("%")
- if v.n then
- term.setCursorPos(v.x, v.b)
- term.write(v.n)
- end
- end
- else
- paintutils.drawImage(v.d, v.x, v.y)
- if not preview then
- term.setCursorPos(v.x, v.y)
- term.write("+")
- if v.n then
- term.setCursorPos(v.x, v.b)
- term.write(v.n)
- end
- end
- end
- end
- if not preview then
- term.setCursorPos(1, th)
- term.setTextColor(colors.gray)
- term.setBackgroundColor(colors.black)
- write("Current Menu: "..gui_menu)
- local s = file_name or "Untitled"
- term.setCursorPos(tw - string.len(s), th)
- term.write(s)
- end
- end
- local function mod_read( _sReplaceChar, _tHistory, wid, starttext)
- term.setCursorBlink( true )
- local sLine = starttext or ""
- local nHistoryPos = nil
- local nPos = (starttext and starttext:len()) or 0
- if _sReplaceChar then
- _sReplaceChar = string.sub( _sReplaceChar, 1, 1 )
- end
- local w, h = term.getSize()
- local sx, sy = term.getCursorPos()
- w = sx + wid - 1
- local function redraw( _sCustomReplaceChar )
- local nScroll = 0
- if sx + nPos >= w then
- nScroll = (sx + nPos) - w
- end
- term.setCursorPos( sx, sy )
- local sReplace = _sCustomReplaceChar or _sReplaceChar
- if sReplace then
- term.write( string.rep(sReplace, string.len(sLine) - nScroll) )
- else
- term.write( string.sub( sLine, nScroll + 1 ) )
- end
- term.setCursorPos( sx + nPos - nScroll, sy )
- end
- redraw()
- while true do
- local sEvent, param = os.pullEvent()
- if sEvent == "char" then
- sLine = string.sub( sLine, 1, nPos ) .. param .. string.sub( sLine, nPos + 1 )
- nPos = nPos + 1
- redraw()
- elseif sEvent == "key" then
- if param == keys.enter then
- -- Enter
- break
- elseif param == keys.left then
- -- Left
- if nPos > 0 then
- nPos = nPos - 1
- redraw()
- end
- elseif param == keys.right then
- -- Right
- if nPos < string.len(sLine) then
- nPos = nPos + 1
- redraw()
- end
- elseif param == keys.up or param == keys.down then
- -- Up or down
- if _tHistory then
- redraw(" ");
- if param == keys.up then
- -- Up
- if nHistoryPos == nil then
- if #_tHistory > 0 then
- nHistoryPos = #_tHistory
- end
- elseif nHistoryPos > 1 then
- nHistoryPos = nHistoryPos - 1
- end
- else
- -- Down
- if nHistoryPos == #_tHistory then
- nHistoryPos = nil
- elseif nHistoryPos ~= nil then
- nHistoryPos = nHistoryPos + 1
- end
- end
- if nHistoryPos then
- sLine = _tHistory[nHistoryPos]
- nPos = string.len( sLine )
- else
- sLine = ""
- nPos = 0
- end
- redraw()
- end
- elseif param == keys.backspace then
- -- Backspace
- if nPos > 0 then
- redraw(" ");
- sLine = string.sub( sLine, 1, nPos - 1 ) .. string.sub( sLine, nPos + 1 )
- nPos = nPos - 1
- redraw()
- end
- elseif param == keys.home then
- -- Home
- nPos = 0
- redraw()
- elseif param == keys.delete then
- if nPos < string.len(sLine) then
- redraw(" ");
- sLine = string.sub( sLine, 1, nPos ) .. string.sub( sLine, nPos + 2 )
- redraw()
- end
- elseif param == keys["end"] then
- -- End
- nPos = string.len(sLine)
- redraw()
- end
- end
- end
- term.setCursorBlink( false )
- term.setCursorPos( w + 1, sy )
- print()
- return sLine
- end
- local function textbox(prompt, starttext)
- sleep(0)
- term.setBackgroundColor(colors.black)
- term.clear()
- drawGui()
- local wid = ((prompt:len() <= 15 and 20) or prompt:len() + 5)
- local startx = tw/2 - wid/2
- local starty = ((th%2==1 and th/2) or ((th/2)-1)) - 2 -- 4/2
- term.setBackgroundColor(colors.lightGray)
- for i = 0, 3 do
- term.setCursorPos(startx, starty + i)
- print(string.rep(" ", wid))
- end
- term.setCursorPos(startx + 1, starty + 1)
- term.setTextColor(colors.black)
- print(prompt)
- term.setBackgroundColor(colors.gray)
- term.setCursorPos(startx + 1, starty + 2)
- print(string.rep(" ", wid-2))
- term.setCursorPos(startx + 1, starty + 2)
- term.setTextColor(colors.white)
- return mod_read(nil, nil, wid-2, starttext)
- end
- local function text(...)
- term.setBackgroundColor(colors.black)
- term.clear()
- drawGui()
- local wid = 0
- local strs = {...}
- for i,v in pairs(strs) do
- local _wid = ((v:len() <= 15 and 20) or v:len() + 5)
- wid = (_wid > wid and _wid) or wid
- end
- local startx = tw/2 - wid/2
- local starty = ((th%2==1 and th/2) or ((th/2)-1)) - 1 -- ~ 3/2
- term.setBackgroundColor(colors.lightGray)
- for i = 0, #strs + 1 do
- term.setCursorPos(startx, starty + i)
- print(string.rep(" ", wid))
- end
- for i,v in pairs(strs) do
- term.setCursorPos(startx + 1, starty + i)
- term.setTextColor(colors.gray)
- print(v)
- end
- os.pullEvent()
- return true
- end
- local function rightClick(x, y)
- local menu
- local index
- local obj
- for i = #gui_objs[gui_menu], 1, -1 do
- if x >= gui_objs[gui_menu][i].x and x <= gui_objs[gui_menu][i].a and y >= gui_objs[gui_menu][i].y and y <= gui_objs[gui_menu][i].b then
- if not gui_objs[gui_menu][i].nfp then
- menu = {
- {" Set Text ", 10},
- {" Delete ", 11},
- {" Background Color ", 12},
- {" Text Color ", 13},
- {" Move Up ", 14},
- {" Move Down ", 15},
- {" Set Name ", 16},
- {" ---------------- ", -1},
- {" New Object ", 1},
- {" New NFP Image ", 2},
- {" New Menu ", 3},
- {" Delete Menu ", 4},
- {" Goto Menu ", 5},
- --{" ---------------- ", -1},
- --{" Save ", 20},
- --{" Load ", 21},
- }
- index = i
- obj = gui_objs[gui_menu][index]
- break
- else
- menu = {
- {" Delete ", 11},
- {" Move Up ", 14},
- {" Move Down ", 15},
- {" ---------------- ", -1},
- {" New Object ", 1},
- {" New NFP Image ", 2},
- {" New Menu ", 3},
- {" Delete Menu ", 4},
- {" Goto Menu ", 5},
- --{" ---------------- ", -1},
- --{" Save ", 20},
- --{" Load ", 21},
- }
- index = i
- obj = gui_objs[gui_menu][index]
- break
- end
- end
- end
- if not menu then
- menu = {
- {" New Object ", 1},
- {" New NFP Image ", 2},
- {" New Menu ", 3},
- {" Delete Menu ", 4},
- {" Goto Menu ", 5},
- --{" ------------ ", -1},
- --{" Save ", 20},
- --{" Load ", 21},
- }
- end
- local startx = (x < tw - menu[1][1]:len() and x) or (tw - menu[1][1]:len())
- local starty = (y < th - #menu and y) or (th - #menu)
- term.setTextColor(colors.white)
- term.setBackgroundColor(colors.gray)
- for i,v in pairs(menu) do
- term.setCursorPos(startx, starty + i)
- term.write(v[1])
- end
- while true do
- local event = {os.pullEvent("mouse_click")}
- if event[3] >= startx and event[3] <= startx + menu[1][1]:len() then
- if menu[event[4] - starty] then
- local option = menu[event[4] - starty][2]
- if option ~= -1 then
- -- Misc. Options
- if option == 1 then -- new object
- newObject(x, y, x + 6, y + 4, colors.white, colors.black)
- elseif option == 2 then -- new image
- local path = textbox("Image Path")
- newImage(x, y, paintutils.loadImage(path))
- elseif option == 3 then -- new menu
- local name = textbox("Create Menu")
- gui_objs[name] = {}
- gui_menu = name
- elseif option == 4 then -- delete menu
- local name = textbox("Delete Menu")
- gui_objs[name] = nil
- if gui_menu == name then if not gui_objs.default then gui_objs.default = {} end gui_menu = "default" end
- elseif option == 5 then -- goto menu
- gui_menu = textbox("Go to Menu")
- if not gui_objs[gui_menu] then gui_objs[gui_menu] = {} end
- -- Object Options
- elseif option == 10 then -- add text
- obj.t = textbox("Object Text", obj.t)
- elseif option == 11 then -- delete
- table.remove(gui_objs[gui_menu], index)
- elseif option == 12 then -- background color
- obj.bc = colors[textbox("Background Color")] or obj.bc
- elseif option == 13 then -- text color
- obj.tc = colors[textbox("Text Color")] or obj.tc
- elseif option == 14 then -- move up
- if index ~= #gui_objs[gui_menu] then
- local obj = table.remove(gui_objs[gui_menu], index)
- table.insert(gui_objs[gui_menu], index + 1, obj)
- end
- elseif option == 15 then -- move down
- if index ~= 1 then
- local obj = table.remove(gui_objs[gui_menu], index)
- table.insert(gui_objs[gui_menu], index - 1, obj)
- end
- elseif option == 16 then
- obj.n = textbox("Name")
- if obj.n == "" then obj.n = nil end
- -- File Options
- elseif option == 20 then -- Save
- local name = textbox("Save As")
- local file = io.open(name, "w")
- file:write(textutils.serialize(gui_objs))
- file:close()
- elseif option == 21 then -- Load
- local name = textbox("Open")
- local file = io.open(name, "r")
- local ok, obj = pcall(textutils.unserialize, file:read("*a"))
- if type(obj) == "table" then
- gui_objs = obj
- elseif not ok then
- text("Error Loading:", obj)
- else
- text("Invalid Type:", type(obj) .. " (" .. tostring(obj) .. ")")
- end
- file:close()
- end
- break
- end
- else
- break
- end
- else
- break
- end
- end
- end
- local function filemenu()
- local x, y = 2, 1
- local menu = {
- {" [O]pen ", 1},
- {" [S]ave ", 2},
- {" Save [A]s ", 3},
- {" --------- ", -1},
- {" [P]review ", 5},
- {" --------- ", -1},
- {" [E]xit ", 10},
- }
- local menukeys = {
- [keys.o] = 1,
- [keys.s] = 2,
- [keys.a] = 3,
- [keys.p] = 5,
- [keys.e] = 10,
- [keys.t] = 10,
- [keys.leftCtrl] = 13,
- }
- local startx = (x < tw - menu[1][1]:len() and x) or (tw - menu[1][1]:len())
- local starty = (y < th - #menu and y) or (th - #menu)
- term.setTextColor(colors.white)
- term.setBackgroundColor(colors.gray)
- for i,v in pairs(menu) do
- term.setCursorPos(startx, starty + i)
- term.write(v[1])
- end
- while true do
- local event = {os.pullEvent()}
- local option
- if event[1] == "mouse_click" then
- if event[3] >= startx and event[3] <= startx + menu[1][1]:len() then
- if menu[event[4] - starty] then
- option = menu[event[4] - starty][2]
- end
- end
- elseif event[1] == "key" then
- if menukeys[event[2]] then option = menukeys[event[2]] end
- end
- if option and option ~= -1 then
- if option == 1 then -- open
- local name = textbox("Open")
- local file = io.open(name, "r")
- local ok, obj = pcall(textutils.unserialize, file:read("*a"))
- if type(obj) == "table" then
- gui_objs = obj
- elseif not ok then
- text("Error Loading:", obj)
- else
- text("Invalid Type:", type(obj) .. " (" .. tostring(obj) .. ")")
- end
- file:close()
- break
- elseif option == 2 then -- save
- if not file_name then
- file_name = textbox("Save As")
- end
- local file = io.open(file_name, "w")
- file:write(textutils.serialize(gui_objs))
- file:close()
- break
- elseif option == 3 then
- file_name = textbox("Save As")
- local file = io.open(file_name, "w")
- file:write(textutils.serialize(gui_objs))
- file:close()
- break
- elseif option == 5 then -- preview
- preview = not preview
- break
- elseif option == 10 then -- exit
- return true
- elseif option == 13 then
- break
- end
- elseif not option then
- break
- end
- end
- end
- if args[1] then
- local file = io.open(args[1], "r")
- local ok, obj = pcall(textutils.unserialize, file:read("*a"))
- if type(obj) == "table" then
- gui_objs = obj
- elseif not ok then
- text("Error Loading:", obj)
- else
- text("Invalid Type:", type(obj) .. " (" .. tostring(obj) .. ")")
- end
- file:close()
- else
- gui_objs = {default={}}
- end
- local dragging
- local drag_mode
- local menulist
- while true do
- term.setBackgroundColor(colors.black)
- term.clear()
- drawGui()
- local event = {os.pullEvent()}
- if event[1] == "mouse_click" and event[2] == 1 then
- -- start dragging if clicked on the top left or bottom right
- dragging = nil
- for i = #gui_objs[gui_menu], 1, -1 do
- local obj = gui_objs[gui_menu][i]
- if event[3] == obj.a and event[4] == obj.b then
- dragging = i
- drag_mode = 2
- break
- elseif event[3] == obj.x and event[4] == obj.y then
- dragging = i
- drag_mode = 1
- break
- end
- end
- elseif event[1] == "mouse_drag" and dragging then
- -- drag
- if drag_mode == 1 then
- if not gui_objs[gui_menu][dragging].nfp then
- gui_objs[gui_menu][dragging].a = event[3] + w(gui_objs[gui_menu][dragging]) - 1
- gui_objs[gui_menu][dragging].b = event[4] + h(gui_objs[gui_menu][dragging]) - 1
- end
- gui_objs[gui_menu][dragging].x = event[3]
- gui_objs[gui_menu][dragging].y = event[4]
- elseif drag_mode == 2 and not gui_objs[gui_menu][dragging].nfp then
- gui_objs[gui_menu][dragging].a = (event[3] >= gui_objs[gui_menu][dragging].x and event[3]) or gui_objs[gui_menu][dragging].x
- gui_objs[gui_menu][dragging].b = (event[4] >= gui_objs[gui_menu][dragging].y and event[4]) or gui_objs[gui_menu][dragging].y
- end
- elseif event[1] == "mouse_click" and event[2] == 2 then
- -- right-click menu
- dragging = nil
- rightClick(event[3], event[4])
- elseif event[1] == "key" then
- if event[2] == keys.left then
- local this_menu
- menulist = {}
- for i,v in pairs(gui_objs) do
- local index = #menulist + 1
- menulist[index] = i
- if i == gui_menu then this_menu = index end
- end
- gui_menu = menulist[(this_menu % #menulist) + 1]
- elseif event[2] == keys.right then
- local this_menu
- menulist = {}
- for i,v in pairs(gui_objs) do
- local index = #menulist + 1
- menulist[index] = i
- if i == gui_menu then this_menu = index end
- end
- gui_menu = menulist[((this_menu-2) % #menulist) + 1]
- elseif event[2] == keys.leftCtrl then
- local exit = filemenu()
- if exit then
- term.setTextColor(colors.white)
- term.setBackgroundColor(colors.black)
- term.clear()
- term.setCursorPos(1, 1)
- break
- end
- end
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement