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

[Not Solved]Advanced Term Scrolling

Started by CCGrimHaxor, 13 February 2015 - 10:30 AM
CCGrimHaxor #1
Posted 13 February 2015 - 11:30 AM
Hey guys so I kind of decided what I want on the scrolling
So I have tried to look in the edit program code but I don't understand anything in there.

So I wanna do the following:
  • Be able to use mouse wheel to scroll up and down
  • Be able to use the arrow keys to select an item in the table and scroll down if we hit the bottom display
  • When I press enter or click on an option I need it to execute a function
That's basicly it.
But the problem I am not really good at guis so idk how this goes.
I have read the explanations but I don't understand how to port that into code.

Thanks
Edited on 27 February 2015 - 06:20 PM
Dragon53535 #2
Posted 13 February 2015 - 12:46 PM
First answer, would be a semi easy way to achieve. If you're using the window API and creating what your text is as a window. You can use the scroll function to scroll down with text, however that would possibly mess up with if you want to scroll up, dunno if it can be used for that.

Keep in mind though that the Edit program by default does have this functionality, and you could rip it from there.

I'll actually do so myself :D/>

Ripped from edit program

elseif sEvent == "mouse_scroll" then
  if not bMenu then
   if param == -1 then
	-- Scroll up
	if scrollY > 0 then
	 -- Move cursor up
	 scrollY = scrollY - 1
	 redrawText()
	end
  
   elseif param == 1 then
	-- Scroll down
	local nMaxScroll = #tLines - (h-1)
	if scrollY < nMaxScroll then
	 -- Move cursor down
	 scrollY = scrollY + 1
	 redrawText()
	end
  
   end
  end

Function:


term.scroll(num lines)
window.scroll(num lines)
Replace window with the variable containing the window.

As for your second question. You'd have to keep a knowledge of where this "button" of text is. If you're having it on your GUI (Which i'm viewing as a border around the text) then you should be able to decently hard code in a way to read the click with mouse click inputs. Of course you'd have to be on an advanced computer.

If you're having it in a way as a hyperlink in the text then that's quite a bit more tricky. You'd have to keep noticeable track of where the link is whenever you scroll and as such would then have to know how far you scrolled.
MKlegoman357 #3
Posted 13 February 2015 - 01:39 PM
The ideal solution would be to either use a GUI library or write one yourself (that's what I would do :P/>/>). One way to make scrolling would be to redraw everything on the screen whenever needed (when you first run the app or scroll thee page) and always redraw it depending on a scroll variable. When you scroll with your mouse (mouse_scroll event) you would change the scroll variable accordingly. The scroll variable itself could be, for example, a number counting from 1 to number-of-items-in-scroll-area. So having that, whenever you would redraw the content you would respect the scroll variable. For example, if your list would look like this:


apples
oranges
bananas
tomatoes
potatoes

the scroll area's height would be 3, the scroll variable would be 2 then you would draw from the second line (oranges) to the second line (2) + area's height (3) - 1 = 4 (tomatoes). So only these would be rendered to the screen:


+--------+
|oranges |
|bananas |
|tomatoes|
+--------+

And with that pop-up window. You would have a button and whenever it was pressed you could render a new window or canvas on top of everything.
Edited on 13 February 2015 - 12:40 PM
CCGrimHaxor #4
Posted 27 February 2015 - 07:21 PM
I just updated the post due to I still don't know what to do or what code to use.

And also I needed some extra stuff.
Lyqyd #5
Posted 27 February 2015 - 07:38 PM
What were the problems with the options you were presented with? What issues did you run in to implementing any features you forgot to mention initially? What error messages are you receiving?
KingofGamesYami #6
Posted 27 February 2015 - 07:54 PM
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
	scrollBar( content, offset )
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

I made a nice looking scrolling menu, it's a bit unfinished but it does react to scrolling, dragging, clicking, and keys. To use it, simply call it with string arguments.

Example:

--#include my code here

--#example code
scroll( unpack( fs.list( "/" ) )

I'll be updating it to work better when few arguments are provided.
CCGrimHaxor #7
Posted 27 February 2015 - 08:06 PM
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
	scrollBar( content, offset )
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

I made a nice looking scrolling menu, it's a bit unfinished but it does react to scrolling, dragging, clicking, and keys. To use it, simply call it with string arguments.

Example:

--#include my code here

--#example code
scroll( unpack( fs.list( "/" ) )

I'll be updating it to work better when few arguments are provided.

Thanks

What were the problems with the options you were presented with? What issues did you run in to implementing any features you forgot to mention initially? What error messages are you receiving?

I was having trouble knowing what they ment again not good at understaing things about guis and stuff.
I will know what everything does once presented with the code but a raw explanation just can't do it for me.
I was getting errors because the first one only got half of the code. The second one was explained really good but I kept getting errors adding it to my code…