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

scrollbar

Started by SpencerBeige, 08 March 2015 - 02:00 AM
SpencerBeige #1
Posted 08 March 2015 - 03:00 AM
ive tried it in the past, got it working, but just barely. how can i make a proper scroll bar, only if the text{} table is too large for the screen?
GopherAtl #2
Posted 08 March 2015 - 12:39 PM
I make no guarantees about completeness, but I happened to have this laying around, you may be able to learn something from it…


local args={...}

local filename=args[1]
--if no valid arg specified, just open myself
if not filename or not fs.exists(filename) or fs.isDir(filename) then
  print("usage:\nscroll <filename>")
  return
end


local scrWidth,scrHeight=term.getSize()

local scrollRedir={}


do
  local width, height=scrWidth-2,2
  local curX, curY=1,1
  local lines={"",""}
  local hasScrollBar=false

  function scrollRedir.write(text)
    lines[curY]=lines[curY]..text
    curX=curX+#text
  end

  function scrollRedir.getCursorPos()
    return curX, curY
  end

  function scrollRedir.getSize()
    return width, #lines
  end

  function scrollRedir.scroll(amt)
    --amt will always be 1. Just grow the buffer one line.
    lines[#lines+1]=""
    curY=curY+1
    curX=1
  end

  function scrollRedir.setCursorPos(x,y)
    curX=x
    curY=y
  end

  function scrollRedir.isColor()
    --if you want these to support color, that becomes more of a thing.
    return false;
  end
  scrollRedir.isColour=scrollRedir.isColor

  --we just ignore these
  function scrollRedir.setTextColor() end
  function scrollRedir.setTextColour() end
  function scrollRedir.setBackgroundColor() end
  function scrollRedir.setBackgroundColour() end
  function scrollRedir.setCursorBlink() end

  function scrollRedir.clearLine()
    lines[curY]=""
  end

  function scrollRedir.clear()
    lines={"",""}
    curY=1
    curX=1
  end

  function scrollRedir.getHasScrollBar() return hasScrollBar end
  function scrollRedir.setHasScrollBar(state)
    hasScrollBar=state
    if hasScrollBar then
	  width=scrWidth-1
    else
	  width=scrWidth
    end
  end


  function scrollRedir.getNumLines() return #lines end

  function scrollRedir.draw(startRow)
    term.setTextColor(colors.white)
    term.setBackgroundColor(colors.black)
    for y=1,scrHeight do
	  term.setCursorPos(1,y)
	  term.clearLine()
	  term.write(lines[y+startRow-1] or "")
    end
    if hasScrollBar then
	  term.setTextColor(colors.black)
	  term.setBackgroundColor(colors.white)
	  term.setCursorPos(scrWidth,1)
	  term.write("^")
	  term.setCursorPos(scrWidth,scrHeight)
	  term.write("v")
	  --calculate bar height
	  local barHeight=math.max(1,math.floor(scrHeight*scrHeight/#lines))
	  --and the position
	  local barPos
	  if startRow==1 then
	    barPos=2
	  elseif startRow+scrHeight-1 == #lines then
	    barPos=(scrHeight-barHeight)
	  else
	    local min, max=3,scrHeight-barHeight-2
	    barPos=min+math.floor(startRow/(#lines-scrHeight-1)*(max-min+1)+.5)
	  end
	  for y=2,scrHeight-1 do
	    term.setCursorPos(scrWidth,y)
	    if y>=barPos and y<barPos+barHeight then
		  term.write("=")
	    else
		  term.write("|")
	    end
	  end
    end
  end

  function scrollRedir.cropLast()
    lines[#lines]=nil
  end
end

local text={}

local approxLines=0


do
  local file=io.open(filename,"r")
  for line in file:lines() do
    text[#text+1]=line
    approxLines=approxLines + (math.ceil(#line/scrWidth))
  end
  file:close()
end

local prevRedir=term.current()
local needsScrollBar=true


if approxLines<=scrHeight then
 
  --try without scrollbar
  term.redirect(scrollRedir)
  for i=1,#text do
    print(text)
  end
  --trim the last line, which was just made blank because of newline
  scrollRedir.cropLast()
  term.redirect(prevRedir)
  local w,h=scrollRedir.getSize()
  if h<=scrHeight then
    needsScrollBar=false
  else
    scrollRedir.clear()
  end
end

if needsScrollBar then
  scrollRedir.setHasScrollBar(true)
  term.redirect(scrollRedir)
  for i=1,#text do
    print(text[i])
  end
  scrollRedir.cropLast()
  term.redirect(prevRedir)
end


local scrollPos=1
local maxScroll=scrollRedir.getNumLines()-scrHeight+1
if not scrollRedir.getHasScrollBar() then
  maxScroll=1
end

while true do
  scrollRedir.draw(scrollPos)
  local e={os.pullEvent()}

  if e[1]=="key" then
    if e[2]==keys.down then
	  scrollPos=math.min(scrollPos+1,maxScroll)
    elseif e[2]==keys.up then
	  scrollPos=math.max(scrollPos-1,1)
    elseif e[2]==keys.pageDown then
	  scrollPos=math.min(scrollPos+scrHeight,maxScroll)
    elseif e[2]==keys.pageUp then
	  scrollPos=math.max(scrollPos-scrHeight,1)
    elseif e[2]==keys.home then
	  scrollPos=1
    elseif e[2]==keys["end"] then
	  scrollPos=maxScroll
    elseif e[2]==keys.leftCtrl then
	  break
    end
  end
end

pastebin get J42TYBHP scroll
wieselkatze #3
Posted 08 March 2015 - 12:41 PM
It would be helpful if you posted some code to actually see what you've already got - and what's not working/what should be improved.
You may take a look on this topic - I did already make a post about scroll bars there and how I managed to display them.
KingofGamesYami #4
Posted 08 March 2015 - 11:44 PM
Couple of things here:

1 - if #text >= maxy then (this compares the number of lines in the text table to the maximum y on the screen (would need to be earlier defined by term.getSize())
2 - maxy^2/#text gets you the vertical size of the scroll bar