This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
KingofGamesYami's profile picture

[GUI] Help with multi-layer gui

Started by KingofGamesYami, 25 April 2014 - 03:17 AM
KingofGamesYami #1
Posted 25 April 2014 - 05:17 AM
So, I am trying to make a chat client, however I ran into a problem: Getting the GUI to display properly. I've got the basic 'start' menu down, but can't seem to get the buttons from that menu to turn OFF, or think of a good way to render a variable-length list of buttons (the list is actually strings, not the buttons themselves, and stored in a table which is saved to a file)
Main Code

os.loadAPI("button")

local upper, lower, aSide, contacts = {}, {}, false, false

local modem = peripheral.wrap('back')
if not modem.isOpen(os.getComputerID()) then
 modem.open(os.getComputerID())
end

function sendChat(text, sendID, side)
 while true do
  local w, h = term.getSize()
  term.setCursorPos(aSide['x'], aSide['y'])
  local modem = peripheral.wrap('back')
  modem.transmit(sendID, os.getComputerID(), text)
  coroutine.yield()
 end
end

function receiveChat(event)
  local x, y = term.getCursorPos()
  local w, h = term.getSize()
  if event[3] == uCon then
   term.setCursorPos(uX, uY)
  elseif event[3] == dCon then
   term.setCursorPos(dX, dY)
  end
  term.write(contacts[event[3]]..": "..event[5])
end

chat = coroutine.create(sendChat)
getChat = coroutine.create(receiveChat)

local contacts

if fs.exists("Chat") and fs.isDir("Chat") then
 local file = fs.open("Chat/contacts", "r")
 local data = file.readAll()
 contacts = textutils.unserialize(data)
 file.close()
else
 shell.run("mk dir Chat")
 local file = fs.open("Chat/contacts", "w")
 file.writeLine("{ }")
 file.close()
 contacts = {}
end

function createContact()
 term.clear()
 term.setCursorPos(1, 1)
 term.write("Name: ")
 local name = read()
 term.write("Computer ID: ")
 local ID = read()
 contacts[ID] = name
 file = fs.open("Chat/contacts", "w")
 file.write(textutils.serialize(contacts))
 file.close()
 reset()
end

function displayContacts(side)
 if side == "up" then
  local i, con = 0, {}
  for k, v in pairs(contacts) do
   i = i + 1
   con[i] = contacts[k]
  end
  con1 = button.register(3, 3, 5, 3, colors.black, colors.magenta, con[1], function() contact = con[1] end)
  con2 = button.register(3, 8, 5, 3, colors.black, colors.magenta, con[2], function() contact = con[2] end)
 end
 button.draw()
 button.event({os.pullEvent})
end

function reset()
 term.setBackgroundColor(colors.red)
 term.clear()
 term.setBackgroundColor(colors.blue)
 local w, h = term.getSize()
 for i = 1, h do
  term.setCursorPos(1, i)
  term.write(' ')
  term.setCursorPos(w, i)
  term.write(' ')
 end
 for i = 1, w do
  term.setCursorPos(i, 1)
  term.write(' ')
  term.setCursorPos(i, h/2 + 1)
  term.write(' ')
  term.setCursorPos(i, h)
  term.write(' ')
 end
 term.setBackgroundColor(colors.red)
 term.setCursorPos(2, h/2)
 button.draw()
end

function event()
 local r = ''
 local event = {os.pullEvent()}
 if event[1] == "modem_message" then
  recieveChat(event)
  return event[4]
 elseif event[1] == "char" then
  r = r..event[2]
  term.write(event[2])
  return false
 elseif event[1] == "mouse_click" then
  button.event(event)
  return false
 elseif event[1] == "key" and event[2] == 28 then
  sendChat(r, sendID, aSide)
  return false
 else
  return false
 end
end

function connect(side)
 displayContacts(side)
end

reset()

local uConnect = button.register(9, 5, 9, 3, colors.black, colors.magenta, "Connect", function() connect("up") end)

local dConnect = button.register(7, 10, 13, 3, colors.black, colors.magenta, "New Contact", function() createContact() end)

local register = button.register(9, 15, 9, 3, colors.black, colors.magenta, "Connect", function() connect("down") end)

button.draw()
while true do
 local reply = event()
end

The button api I load on line 1 is found here
I realize that I have redundant functions, I have plans to add stuff and clean up the code a lot. But first, I want to get it to work.
Edited on 25 April 2014 - 03:20 AM
Bomb Bloke #2
Posted 25 April 2014 - 11:10 AM
Best I can make out, the buttons in that API aren't an on / off deal - you press them, some function runs. You press them again - the same function runs. The touchpoint API looks like it may be more suitable for toggles.

Or if you're wondering how to get the buttons off the screen - unregister them, then manually clear the area of the display where they were located.

If I wanted to define pages and pages of variable amounts of buttons (I wouldn't - coding interfaces is boring - but you get the idea), I guess I'd load the particulars into a table filled with sub-tables. I'd then make a function that was rigged to show a given page of buttons from inside that table - pushing a given button would either call the function again (telling it to display a different "page"), or go off and do something non-menu-related.
Edited on 25 April 2014 - 09:11 AM
KingofGamesYami #3
Posted 25 April 2014 - 01:48 PM
The problem with that is, the touchpoint api only works on monitors.
Does anyone know a better API for buttons that works on the terminal? Or how to adapt the touchpoint API to work on the terminal?
Edited on 25 April 2014 - 09:33 PM
Dayrider10 #4
Posted 26 April 2014 - 02:12 AM
The problem with that is, the touchpoint api only works on monitors.
Does anyone know a better API for buttons that works on the terminal? Or how to adapt the touchpoint API to work on the terminal?

Honestly I only suggest using term.setBackgroundColor() and using the click event being that you can't touch the terminal you just click so use the mouse click event.
Bomb Bloke #5
Posted 26 April 2014 - 10:38 AM
I suppose if you ask Lyqyd nicely he may update it to work both ways; rig it so if touchpoint.new() is called with no parameter it uses the default display. But it wouldn't be hard to perform a simple conversion yourself -

Remove the peripheral wrapping / term redirection code. For the most part this involves simply removing lines of code.

Change the "monitor_touch" references to "mouse_click", and remove the associated monitor side check. The two different events are otherwise effectively identical.

At a glance we're talking maybe half a to a full dozen lines to tweak.
Lyqyd #6
Posted 26 April 2014 - 04:33 PM
There's a post on the second or so page of the Touchpoint topic wherein someone has posted a modification that allows it to be used on the terminal, FYI.