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

Making a scroll bar

Started by DannySMc, 25 March 2015 - 04:05 PM
DannySMc #1
Posted 25 March 2015 - 05:06 PM
I am taking a break from co routines to finish my file browser, although I have encountered a small problem, I am trying to add a scroll bar in that allows you to scroll using the mouse wheel and the scroll bar will change, now currently I have this working… but it doesn't exactly work the correct way…

There is no error but the actual size of scroll button/bar is calculated using:
 size = math.ceil(fileslen / 15)
which is the space it has to wok with… Although the actual position of the bar is the problem, so as said before it has 15 spaces to use so I made a code:
EDIT: The size isn't dynamic either :/

pos = 3 + scroll
As this, in the meantime, works but it goes off the screen a lot, so I am not completely sure how to fix this…

This is the code for the function to make the scroll bar:

function xplore.scrollbar(fileslen, scroll)
	draw.box(1, 1, 2, 18, false, "grey", "grey")
	draw.texta("^", 1, 2, false, "white", "grey")
	draw.texta("v", 1, 19, false, "white", "grey")
	fileslen = fileslen / 10
	size = math.ceil(fileslen / 15)
	pos = 2 + math.ceil(scroll + #fileslen / 16)
	draw.texta(fileslen, 40, 1, false, "lime", "grey")
	draw.box(1, 1, pos, size, " ", "lightGrey", "lightGrey")
end

Any help would be appreciated

Here is the api code:

function draw.box(StartX, lengthX, StartY, lengthY, Text, Color, BkgColor)
    local x, y = term.getSize()
    if Color then 
        col.set(Color, BkgColor) 
    end
    if not Text then 
        Text = "*" 
    end
    lengthX = lengthX - 1 
    lengthY = lengthY - 1
    EndX = StartX + lengthX  
    EndY = StartY + lengthY
    term.setCursorPos(StartX, StartY)
    term.write(string.rep(Text, lengthX))
    term.setCursorPos(StartX, EndY)
    term.write(string.rep(Text, lengthX)) 
    for i = StartY, EndY do
        term.setCursorPos(StartX, i)
        term.write(Text)
        term.setCursorPos(EndX, i)    
        term.write(Text)
    end
    col.reset(Color, BkgColor)
    return true  
end


function draw.texta(Text, xx, yy, NextLine, Color, BkgColor)
    term.setCursorPos(xx,yy)
    if Color then 
        col.set(Color, BkgColor) 
    end
    term.write(Text)
    if NextLine then  
        term.setCursorPos(1, NextLine) 
    end
    if Color then 
        col.reset(Color, BkgColor) 
    end
    return true  
end
Edited on 25 March 2015 - 04:13 PM
KingofGamesYami #2
Posted 25 March 2015 - 05:34 PM
I use this… offset increments by 1 for every mouse_scroll event (either up or down). I use a loop though, instead of an API, so you can convert that yourself.


local scrollBar = function( content, offset )
	local contenty = #content * 5
	local barSize = (maxy^2 / contenty)
	for i = 1, maxy do
		if i >= math.abs( offset/(contenty/maxy) ) and i <= math.abs( offset/(contenty/maxy) ) + barSize + 1 then
			term.setBackgroundColor( colors.gray )
		else
			term.setBackgroundColor( colors.lightGray )
		end
		term.setCursorPos( maxx, i )
		term.write( " " )
	end
end
DannySMc #3
Posted 26 March 2015 - 09:23 AM
I use this… offset increments by 1 for every mouse_scroll event (either up or down). I use a loop though, instead of an API, so you can convert that yourself.


local scrollBar = function( content, offset )
	local contenty = #content * 5
	local barSize = (maxy^2 / contenty)
	for i = 1, maxy do
		if i >= math.abs( offset/(contenty/maxy) ) and i <= math.abs( offset/(contenty/maxy) ) + barSize + 1 then
			term.setBackgroundColor( colors.gray )
		else
			term.setBackgroundColor( colors.lightGray )
		end
		term.setCursorPos( maxx, i )
		term.write( " " )
	end
end

With a bit of testing, this works, but it doesn't have a 'bar'… It just has a lightGrey colour that as you scroll down gets rid of the grey background?
So say this is the bar:
||
||
||
||
||
||
and grey is "#", as I scroll down it does this:
# # #
|| # #
|| || #
|| || ||
|| || ||

etc until the whole bar is grey? how do I get like a bar like all scroll bars? like a small little bar inside a bigger one that moves depending on the position of the content and scroll? :S
KingofGamesYami #4
Posted 26 March 2015 - 12:11 PM
Heh, here's the full code I pulled it from… Not all of it is relevant though. It does some unnecessary multiplication to deal with buttons and has some click detection.
Spoiler
local maxx, maxy = term.getSize()

local scrollBar = function( content, offset )
	local contenty = #content * 5
	local barSize = (maxy^2 / contenty)
	for i = 1, maxy do
		if i >= math.abs( offset/(contenty/maxy) ) and i <= math.abs( offset/(contenty/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 contentlen = #content[ i ]
		local x, y = math.ceil((maxx - contentlen)/2), i * 5 - 2 + offset
		if y >=0 and y <= maxy then
			term.setCursorPos( x - 1, y )
			term.write( " " .. content[ i ] .. " " )
			term.setCursorPos( x - 1, y - 1 )
			term.write( string.rep( " ", contentlen + 2 ) )
			term.setCursorPos( x - 1, y + 1 )
			term.write( string.rep( " ", contentlen + 2 ) )
		end
	end
	if #content * 5 > maxy then
		scrollBar( content, offset )
	end
end
local 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) * #content * 5 / maxy
            if offset > 0 then
            	offset = 0
            elseif offset < minScroll then
            	offset = minScroll
            end
            lastx, lasty = event[ 3 ], event[ 4 ]
            display( content, offset )
        elseif event[ 1 ] == "key" then
        	if event[ 2 ] == keys.up then
        		offset = offset + 1
        	elseif event[ 2 ] == keys.down then
        		offset = offset - 1
        	end
        	if offset > 0 then
        		offset = 0
        	elseif offset < minScroll then
        		offset = minScroll
        	end
        	display( content, offset )
		end
	end
end