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

Scrolling Button Menu

Started by KingofGamesYami, 26 February 2015 - 06:40 PM
KingofGamesYami #1
Posted 26 February 2015 - 07:40 PM
messy, inefficient code
local maxx, maxy = term.getSize()

local scrollBar = function( content, offset )
	local barSize = (maxy / (#content*5) * maxy)
	for i = 1, maxy do
		if i >= math.abs( offset/(#content*5/maxy) ) and i <= math.abs( offset/(#content*5/maxy) ) + barSize + 1 then
			term.setBackgroundColor( colors.gray )
		else
			term.setBackgroundColor( colors.lightGray )
		end
		term.setCursorPos( maxx, i )
		term.write( " " )
	end
end
local display = function( content, offset )
	term.setBackgroundColor( colors.white )
	term.clear()
	term.setBackgroundColor( colors.lightGray )
	term.setTextColor( colors.gray )
	for i = 1, #content do
		local x, y = math.ceil((maxx - #content[ i ])/2), i * 5 - 2 + offset
		
		term.setCursorPos( x - 1, y )
		term.write( " " .. content[ i ] .. " " )
		term.setCursorPos( x - 1, y - 1 )
		term.write( string.rep( " ", #content[ i ] + 2 ) )
		term.setCursorPos( x - 1, y + 1 )
		term.write( string.rep( " ", #content[ i ] + 2 ) )
	end
	scrollBar( content, offset )
end
function scroll( ... )
	local content = {...}
	local offset = 0
	local minScroll = maxy - (#content * 5)
	local barClicked = true
	local lastx, lasty
	
	display( content, offset )
	while true do
		local event = {os.pullEvent()}
		if event[ 1 ] == "mouse_scroll" then
			offset = offset - event[ 2 ]
			if offset > 0 then
				offset = 0
			elseif offset < minScroll then
				offset = minScroll
			end
			display( content, offset )
		elseif event[ 1 ] == "mouse_click" then
			barClicked = false
			--check buttons
			for i, v in ipairs( content ) do
				local x, y = math.ceil((maxx - #v)/2), i * 5 - 2 + offset
				if event[ 3 ] >= x-1 and event[ 3 ] <= x + #v and event[ 4 ] >= y - 1 and event[ 4 ] <= y + 1 then
					return v
				end
			end
			--check scrollbar
			if event[ 3 ] == maxx and event[ 4 ] >= math.abs( offset/(#content*5/maxy) ) and event[ 4 ] <= math.abs( offset/(#content*5/maxy) ) + (maxy / (#content*5) * maxy) + 1 then
				barClicked = true
				lastx, lasty = event[ 3 ], event[ 4 ]
			end
		elseif event[ 1 ] == "mouse_drag" and barClicked then
			offset = offset + (event[ 4 ] - lasty)
			lastx, lasty = event[ 3 ], event[ 4 ]
		end
	end
end

local var = scroll( unpack( fs.list( "/" ) ) )
term.clear()
term.setCursorPos( 1, 1 )
term.write( var )

Everything works normally, until I try to drag the scroll bar. I will later have to change the amount added/subtracked, but for now I'd just like it to increment offset.

I'd guess it's this line that's the problem:

			if event[ 3 ] == maxx and event[ 4 ] >= math.abs( offset/(#content*5/maxy) ) and event[ 4 ] <= math.abs( offset/(#content*5/maxy) ) + (maxy / (#content*5) * maxy) + 1 then
Lyqyd #2
Posted 26 February 2015 - 08:27 PM
Okay, everything works normally before you try to drag it, what happens after you try to drag it?
KingofGamesYami #3
Posted 27 February 2015 - 12:15 AM
Nothing. That's the problem.
Lyqyd #4
Posted 27 February 2015 - 12:55 AM
So, the scroll bar appears to not do anything, but the rest of the program still works, or the scroll bar appears to do nothing and then the rest of the program becomes unresponsive? Does the problem appear when you just click the scroll bar, or does it require an attempt to drag it?
Quintuple Agent #5
Posted 27 February 2015 - 12:56 AM

elseif event[ 1 ] == "mouse_drag" and barClicked then
		 offset = offset + (event[ 4 ] - lasty)
		 lastx, lasty = event[ 3 ], event[ 4 ]
end
to

elseif event[ 1 ] == "mouse_drag" then
		offset = offset - (event[ 4 ] - lasty)
		lastx, lasty = event[ 3 ], event[ 4 ]
		display( content, offset )
end
You forgot your display() function also change the offset + (event[ 4 ] - lasty) to offset - (event[ 4 ] - lasty), or else the movement will be backwards, also you might need to multiply the (event[ 4 ] - lasty) by something to scale it with the mouse movement.

Also just a note, (maxy^2 / (#content*5) ) is the same as (maxy /(#content*5) * maxy)
and (offset*maxy)/(#content*5) is the same as offset/(#content*5/maxy)
(does not matter, just looks better in my opinion)

Edit: Doing

offset = offset - (event[ 4 ] - lasty) * ( #content / 5 )
seemed to do the trick, this all worked for me
Spoiler

local maxx, maxy = term.getSize()
local scrollBar = function( content, offset )
	    local barSize = (maxy^2 / (#content*5) )
	    for i = 1, maxy do
			    if i >= math.abs( (offset*maxy)/(#content*5) ) and i <= math.abs( (offset*maxy)/(#content*5) ) + barSize + 1 then
					    term.setBackgroundColor( colors.gray )
			    else
					    term.setBackgroundColor( colors.lightGray )
			    end
			    term.setCursorPos( maxx, i )
			    term.write( " " )
	    end
end
local display = function( content, offset )
	    term.setBackgroundColor( colors.white )
	    term.clear()
	    term.setBackgroundColor( colors.lightGray )
	    term.setTextColor( colors.gray )
	    for i = 1, #content do
			    local x, y = math.ceil((maxx - #content[ i ])/2), i * 5 - 2 + offset
			   
			    term.setCursorPos( x - 1, y )
			    term.write( " " .. content[ i ] .. " " )
			    term.setCursorPos( x - 1, y - 1 )
			    term.write( string.rep( " ", #content[ i ] + 2 ) )
			    term.setCursorPos( x - 1, y + 1 )
			    term.write( string.rep( " ", #content[ i ] + 2 ) )
	    end
	    scrollBar( content, offset )
end
function scroll( ... )
	    local content = {...}
	    local offset = 0
	    local minScroll = maxy - (#content * 5)
	    local barClicked = false
	    local lastx, lasty
 
	    display( content, offset )
	    while true do
  
			    local event = {os.pullEvent()}
			    if event[ 1 ] == "mouse_scroll" then
					    offset = offset - event[ 2 ]
					    if offset > 0 then
							    offset = 0
					    elseif offset < minScroll then
							    offset = minScroll
					    end
					    display( content, offset )
			    elseif event[ 1 ] == "mouse_click" then
					    --check buttons
					    for i, v in ipairs( content ) do
							    local x, y = math.ceil((maxx - #v)/2), i * 5 - 2 + offset
							    if event[ 3 ] >= x-1 and event[ 3 ] <= x + #v and event[ 4 ] >= y - 1 and event[ 4 ] <= y + 1 then
									    return v
							    end
					    end
					    --check scrollbar
					    if event[ 3 ] == maxx and event[ 4 ] >= math.abs( (offset*maxy)/(#content*5) ) and event[ 4 ] <= math.abs( (offset*maxy)/(#content*5) ) + (maxy^2 / (#content*5) ) + 1 then
							    barClicked = true
							    lastx, lasty = event[ 3 ], event[ 4 ]
					    end
			    elseif event[ 1 ] == "mouse_drag" and barClicked then
					    offset = offset - (event[ 4 ] - lasty) * ( #content / 5 )
					    lastx, lasty = event[ 3 ], event[ 4 ]
	  display( content, offset )
			    end
	    end
end
local var = scroll( unpack( fs.list( "/" ) ) )
term.clear()
term.setCursorPos( 1, 1 )
term.write( var )
Edited on 27 February 2015 - 12:03 AM
KingofGamesYami #6
Posted 27 February 2015 - 01:54 AM
So, the scroll bar appears to not do anything, but the rest of the program still works, or the scroll bar appears to do nothing and then the rest of the program becomes unresponsive? Does the problem appear when you just click the scroll bar, or does it require an attempt to drag it?

To clarify, the program simply doesn't respond to clicking and dragging the scroll bar. Other functionality is not affected after attempting to drag the scroll bar. The scroll bar displays properly.

I suspect Quintuple Agent has fixed the issue, I will try this later as I am not able to at present.