I also thought of keeping a complete "log" of all of the functions ran and then running them all at once when you want to restore them, but that seems highly inefficient to me…
This is a read-only snapshot of the ComputerCraft forums,
taken in April 2020.
How to re-create the previous UI
Started by Twijn, 10 December 2015 - 02:20 AMPosted 10 December 2015 - 03:20 AM
So, what I'm trying to do, is have a program run in the background and when something happens (I already have this part figured out completely) it will create a warning on the top of the screen. Then, a few seconds later, it would remove the message and restore the screen that it was at. I have tried using the window API, assuming that it would – once not visible – would do this, however it seems that that is not the case. Instead it just sits there.
I also thought of keeping a complete "log" of all of the functions ran and then running them all at once when you want to restore them, but that seems highly inefficient to me…
I also thought of keeping a complete "log" of all of the functions ran and then running them all at once when you want to restore them, but that seems highly inefficient to me…
Posted 10 December 2015 - 03:43 AM
Show the code you're using to handle this, and we can see what you're attempting.
Posted 10 December 2015 - 03:54 AM
I have this running on startup:
And this running to activate the "warning":
After calling the createWarning function, the screen literally goes blank, like it shut off. I also have found you can't terminate the program.
EDIT: It is actually doing that at the startup.
local Collect = true
local ScreenSaver = {}
sapis = {}
function sapis.toggleSS(bool)
Collect = bool or not Collect
end
local oldC = term.clear
function term.clear(...)
if Collect then
ScreenSaver = {}
end
return oldC(unpack(args))
end
for i,v in pairs(term)do
if i:lower() ~= "clear" then
local oldFunc = v
term[i] = function(...)
if Collect then
local tbl = {
["Function"] = oldFunc;
["Arguments"] = args;
}
table.insert(ScreenSaver,tbl)
end
return oldFunc(unpack(args))
end
end
end
for i,v in pairs(paintutils)do
if i:lower() ~= "loadimage" then
local oldFunc = v
term[i] = function(...)
if Collect then
local tbl = {
["Function"] = oldFunc;
["Arguments"] = args;
}
table.insert(ScreenSaver,tbl)
end
return oldFunc(unpack(args))
end
end
end
And this running to activate the "warning":
local function createWarning(func,args)
sapis.toggleSS(false)
local lastBC = term.getBackgroundColor()
local lastTC = term.getTextColor()
args = args or "None Specified"
local run = true
buttonapis.backupButtons()
term.setTextColor(colors.white)
paintutils.drawFilledBox(1,1,w,h,colors.red)
term.setCursorPos(1,1)
term.write("An unauthorized program is trying to use "..func..".")
term.setCursorPos(1,2)
term.write("Given Arguments: "..args)
term.setCursorPos(1,3)
term.write("Allow this?")
buttonapis.addButton(w-6,2,w-4,3,"yes")
buttonapis.addButton(w-2,2,w-1,3,"no")
term.setCursorPos(w-6,3)
term.write("Yes")
term.setCursorPos(w-2,3)
term.write("No")
bfunctions.yes = function(x,y,func)
restore()
end
bfunctions.no = function(x,y,func)
restore()
end
while run do
buttonapis.handleEvent()
end
term.getBackgroundColor(lastBC)
term.getTextColor(lastTC)
sapis.toggleSS(true)
end
After calling the createWarning function, the screen literally goes blank, like it shut off. I also have found you can't terminate the program.
EDIT: It is actually doing that at the startup.
Edited on 10 December 2015 - 03:00 AM
Posted 10 December 2015 - 04:03 AM
Curious question, why are you reverting a state and not just using another window?
Posted 10 December 2015 - 04:04 AM
Put the main screen in a window and when you hide the popup call `window.redraw()`.
Example:
It waits 5 seconds then opens a popup then 5 seconds later it closes it. (then exits 5 seconds after that)
Example:
It waits 5 seconds then opens a popup then 5 seconds later it closes it. (then exits 5 seconds after that)
local mainCo = coroutine.create(function()
shell.run("shell")
end)
local mainWin = window.create(term.current(), 1, 1, term.getSize())
local mainFilter
local prev = term.redirect(mainWin)
_, mainFilter = coroutine.resume(mainCo)
term.redirect(prev)
local function resize()
mainWin.reposition(1, 1, term.getSize())
end
local w, h = term.getSize()
local popup
local popupWidth, popupHeight = 15, 10
local timer = os.startTimer(5)
local stage = 0
while true do
local ev = {os.pullEventRaw()}
if ev[1] == 'term_resize' then
w, h = term.getSize()
resize()
elseif ev[1] == 'timer' and ev[2] == timer then
if stage == 0 then
popup = window.create(term.current(), math.floor(w/2 - popupWidth/2), math.floor(h/2 - popupHeight/2), popupWidth, popupHeight)
local prevP = term.redirect(popup)
term.setBackgroundColor(colors.gray)
term.clear()
term.setCursorPos(1, 1)
print("popup")
term.redirect(prevP)
popup.redraw()
mainWin.restoreCursor()
elseif stage == 1 then
popup.setVisible(false)
mainWin.redraw()
mainWin.restoreCursor()
elseif stage == 2 then
break
end
timer = os.startTimer(5)
stage = stage + 1
end
if mainFilter == nil or mainFilter == ev[1] then
local prevTerm = term.redirect(mainWin)
_, mainFilter = coroutine.resume(mainCo, unpack(ev))
term.redirect(prevTerm)
mainWin.redraw()
if popup then
popup.redraw()
mainWin.restoreCursor()
end
end
end
Edited on 10 December 2015 - 03:15 AM
Posted 12 December 2015 - 12:03 AM
That clears the entire screen… I'd like it to keep the screen behind it, if possible.Put the main screen in a window and when you hide the popup call `window.redraw()`.
Example:
It waits 5 seconds then opens a popup then 5 seconds later it closes it. (then exits 5 seconds after that)local mainCo = coroutine.create(function() shell.run("shell") end) local mainWin = window.create(term.current(), 1, 1, term.getSize()) local mainFilter local prev = term.redirect(mainWin) _, mainFilter = coroutine.resume(mainCo) term.redirect(prev) local function resize() mainWin.reposition(1, 1, term.getSize()) end local w, h = term.getSize() local popup local popupWidth, popupHeight = 15, 10 local timer = os.startTimer(5) local stage = 0 while true do local ev = {os.pullEventRaw()} if ev[1] == 'term_resize' then w, h = term.getSize() resize() elseif ev[1] == 'timer' and ev[2] == timer then if stage == 0 then popup = window.create(term.current(), math.floor(w/2 - popupWidth/2), math.floor(h/2 - popupHeight/2), popupWidth, popupHeight) local prevP = term.redirect(popup) term.setBackgroundColor(colors.gray) term.clear() term.setCursorPos(1, 1) print("popup") term.redirect(prevP) popup.redraw() mainWin.restoreCursor() elseif stage == 1 then popup.setVisible(false) mainWin.redraw() mainWin.restoreCursor() elseif stage == 2 then break end timer = os.startTimer(5) stage = stage + 1 end if mainFilter == nil or mainFilter == ev[1] then local prevTerm = term.redirect(mainWin) _, mainFilter = coroutine.resume(mainCo, unpack(ev)) term.redirect(prevTerm) mainWin.redraw() if popup then popup.redraw() mainWin.restoreCursor() end end end
Posted 12 December 2015 - 02:30 AM
That clears the entire screen…
Erm, no it doesn't? Did you try it? The only clear call I can see in there is aimed at the popup's window, and on testing the code snippet out, I find it works for me.
Posted 12 December 2015 - 02:39 AM
Yes, it clears everything that's on screen when you start it. But if it was startup (and didn't exit after 15 seconds) it would seem like just a normal shell (except that it would open a popup after 5 seconds). I'm guessing you want this for DevOS which already replaces startup which makes clearing everything that was previously there fine.
It will clear the screen, since the main window covers the entire screen. But it will just put another shell there so it might not look exactly like it clears the screen.That clears the entire screen…
Erm, no it doesn't? Did you try it? The only clear call I can see in there is aimed at the popup's window, and on testing the code snippet out, I find it works for me.
Posted 12 December 2015 - 02:35 PM
How, then, would I make the screen stay behind it?Yes, it clears everything that's on screen when you start it. But if it was startup (and didn't exit after 15 seconds) it would seem like just a normal shell (except that it would open a popup after 5 seconds). I'm guessing you want this for DevOS which already replaces startup which makes clearing everything that was previously there fine.It will clear the screen, since the main window covers the entire screen. But it will just put another shell there so it might not look exactly like it clears the screen.That clears the entire screen…
Erm, no it doesn't? Did you try it? The only clear call I can see in there is aimed at the popup's window, and on testing the code snippet out, I find it works for me.
Posted 12 December 2015 - 11:45 PM
There is no way to get the contents of the screen after it has been written. You need to record it somehow (starting on startup), whether that's redirecting to a window or something else.
Posted 12 December 2015 - 11:49 PM
The thing is that in order to do this "properly" you need to have access to the window the script you want to put pop-ups over is running in, and you need to have access to the parent of that window. The only way to be sure you have those two things is to create the script's window yourself and then start that script within it.
If you really don't want to do that (and it beats me as to why you wouldn't), then you can cheat a little: at least, if you're using an advanced computer. Multishell automatically runs shell through a window, and it's a fair bet that the window's parent will be term.native(). That might not be true when your pop-up script runs, but it probably will be.
So the code would go along these lines:
If you really don't want to do that (and it beats me as to why you wouldn't), then you can cheat a little: at least, if you're using an advanced computer. Multishell automatically runs shell through a window, and it's a fair bet that the window's parent will be term.native(). That might not be true when your pop-up script runs, but it probably will be.
So the code would go along these lines:
-- Make sure we have multishell:
if not multishell then error("This requires an advanced computer with multishell active.") end
-- Wait until this script is running in the current multishell tab:
while multishell.getCurrent() ~= multishell.getFocus() do sleep(5) end -- An event for tab switching would be helpful here...
-- Make sure we have a window:
local win = term.current()
if not win.redraw then error("Multishell tab has already been redirected away from its window.") end
-- Make an assumption:
local parent = term.native()
-- Draw a pop-up:
local popup = window.create(parent, 10, 10, 5, 5)
popup.setBackgroundColour(colours.red)
popup.clear()
-- Wait a while:
sleep(5)
-- Revert back to the old screen:
win.redraw()
Edited on 12 December 2015 - 10:51 PM
Posted 13 December 2015 - 02:37 AM
That one works! Thank you!The thing is that in order to do this "properly" you need to have access to the window the script you want to put pop-ups over is running in, and you need to have access to the parent of that window. The only way to be sure you have those two things is to create the script's window yourself and then start that script within it.
If you really don't want to do that (and it beats me as to why you wouldn't), then you can cheat a little: at least, if you're using an advanced computer. Multishell automatically runs shell through a window, and it's a fair bet that the window's parent will be term.native(). That might not be true when your pop-up script runs, but it probably will be.
So the code would go along these lines:-- Make sure we have multishell: if not multishell then error("This requires an advanced computer with multishell active.") end -- Wait until this script is running in the current multishell tab: while multishell.getCurrent() ~= multishell.getFocus() do sleep(5) end -- An event for tab switching would be helpful here... -- Make sure we have a window: local win = term.current() if not win.redraw then error("Multishell tab has already been redirected away from its window.") end -- Make an assumption: local parent = term.native() -- Draw a pop-up: local popup = window.create(parent, 10, 10, 5, 5) popup.setBackgroundColour(colours.red) popup.clear() -- Wait a while: sleep(5) -- Revert back to the old screen: win.redraw()