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

Generating Scrollable buttons in the terminal from a table

Started by vargaszm, 08 July 2014 - 12:52 AM
vargaszm #1
Posted 08 July 2014 - 02:52 AM
I'm working on a programming class for kids using turtles, various grades 1-6 depending on each class. My coding skills are not that strong and one thing i need is to make their list of programs mouse-clickable. It's hurting my brain thinking about it, but i have enough ideas i know i could do it with some help. I recently started playing around with stateless iterators, but I'm still building on very rusty basic skills from over 10 years ago.

Here's the code for the rednet turtle client: http://pastebin.com/XxSqVTCa
Bomb Bloke #2
Posted 08 July 2014 - 03:51 AM
That's quite a project you've got going there. :lol:/>

I just happened to write a menu the other day (for this thing); I've stripped the code down to a basic set of function calls which I reckon you should be able to customise and/or integrate into what you've got:

Spoiler
local xSize, ySize, myEvent = term.getSize()

-- Returns whether a click was performed at a given location.
-- If one parameter is passed, it checks to see if y is [1].
-- If two parameters are passed, it checks to see if x is [1] and y is [2].
-- If three parameters are passed, it checks to see if x is between [1]/[2] (non-inclusive) and y is [3].
-- If four paramaters are passed, it checks to see if x is between [1]/[2] and y is between [3]/[4] (non-inclusive).
local function clickedAt(...)
	if myEvent[1] ~= "mouse_click" then return false end
	if #arg == 1 then return (arg[1] == myEvent[4])
	elseif #arg == 2 then return (myEvent[3] == arg[1] and myEvent[4] == arg[2])
	elseif #arg == 3 then return (myEvent[3] > arg[1] and myEvent[3] < arg[2] and myEvent[4] == arg[3])
	else return (myEvent[3] > arg[1] and myEvent[3] < arg[2] and myEvent[4] > arg[3] and myEvent[4] < arg[4]) end
end

-- Returns whether one of a given set of keys was pressed.
local function pressedKey(...)
	if myEvent[1] ~= "key" then return false end
	for i=1,#arg do if arg[i] == myEvent[2] then return true end end
	return false
end

local function menu(displayList)
	local position, lastPosition = 1, 0
	term.setBackgroundColour(colours.black)

	while true do
		-- Update file list display.
		if position ~= lastPosition then for y = 1, ySize do
			local thisLine = y + position - math.floor(ySize / 2) - 1

			if displayList[thisLine] then
				if thisLine == position then
					term.setCursorPos(math.floor((xSize - #displayList[thisLine] - 8) / 2) + 1, y)
					term.clearLine()
					term.setTextColour(term.isColour() and colours.cyan or colours.black)
					term.write("> > ")
					term.setTextColour(term.isColour() and colours.blue or colours.white)
					term.write(displayList[thisLine])
					term.setTextColour(term.isColour() and colours.cyan or colours.black)
					term.write(" < <")
				else
					term.setCursorPos(math.floor((xSize - #displayList[thisLine]) / 2) + 1, y)
					term.clearLine()

					if y == 1 or y == ySize then
						term.setTextColour(colours.black)
					elseif y == 2 or y == ySize - 1 then
						term.setTextColour(term.isColour() and colours.grey or colours.black)
					elseif y == 3 or y == ySize - 2 then
						term.setTextColour(term.isColour() and colours.lightGrey or colours.white)
					else term.setTextColour(colours.white) end

					term.write(displayList[thisLine])
				end
			else
				term.setCursorPos(1,y)
				term.clearLine()
			end
		end end
		lastPosition = position
		
		-- Wait for input.
		myEvent = {os.pullEvent()}

		-- Move down the list.
		if pressedKey(keys.down,keys.s) or (myEvent[1] == "mouse_scroll" and myEvent[2] == 1) then
			position = position == #displayList and 1 or (position + 1)

		-- Move up the list.
		elseif pressedKey(keys.up,keys.w) or (myEvent[1] == "mouse_scroll" and myEvent[2] == -1) then
			position = position == 1 and #displayList or (position - 1)

		-- Item selected, return its name.
		elseif pressedKey(keys.enter, keys.space) or clickedAt(math.floor(ySize / 2) + 1) then
			return displayList[position]

		-- User clicked somewhere on the file list; move that entry to the currently-selected position.
		elseif clickedAt(0, xSize + 1, 0, ySize + 1) then
			position = position + myEvent[4] - math.floor(ySize / 2) - 1
			position = position > #displayList and #displayList or position
			position = position < 1 and 1 or position
		end
	end
end

local exampleList = {"this","is","a","possible","list","of","items","you","might","have","for","display","on","your","menu","that","you","got","over","rednet","from","your","server"}

local selectedScript = menu(exampleList)

term.clear()
print("The user selected \""..selectedScript.."\".")
Edited on 08 July 2014 - 10:03 PM
Geforce Fan #3
Posted 08 July 2014 - 03:57 AM
you're definitely going to want to brush up on coding skills before attempting your project. luckily the Lua projects offers free online manuals(5.1, the version CC uses: http://www.lua.org/manual/5.1/index.html#contents ) though it certainly helps to have a physical copy. You might want a physical copy for the classroom too.
vargaszm #4
Posted 08 July 2014 - 09:00 PM
These kids barely understand what a computer is or where the keys are, the class is highly nerfed. The goal is more to teach them a few basic structures and make them feel comfortable with what programming is. I don't have a lot of time to make an impression so I'm more focused on creating something they can take home and will want to use at home.
vargaszm #5
Posted 08 July 2014 - 09:17 PM
the scroller is nice, and the note block vid is pretty cool. I can def adapt this, and i love that you added in the fading. Details are gold. Danke schoen.