HELP! How to create a multipage list?

Started by Mazepa, May 12, 2022, 03:15 PM

Previous topic - Next topic

Mazepa

Hello,

I want to create a multi-page application list,
but I have no idea how to implement it :(

I have attached the desired result.

This is the code I wrote, I'm waiting for suggestions.
Thanks in advance.
term.clear()
w, h = term.getSize()
nProg = 1
PROGRAMS = {}
PROGRAMS = fs.list("SimpleOS/Data/Programs/")

-- Functions

function drawBorder()
term.setCursorPos(1, 1)
write("+")
term.setCursorPos(1, h)
write("+")
term.setCursorPos(w, 1)
write("+")
term.setCursorPos(w, h)
write("+")

i = 0
term.setCursorPos(2, 1)
while i < w-2 do
write("-")
i = i + 1
end

i = 0
term.setCursorPos(2, h)
while i < w-2 do
write("-")
i = i + 1
end

i = 0
term.setCursorPos(1, 2)
while i < h-2 do
print("|")
i = i + 1
end

i = 0
term.setCursorPos(w, 2)
while i < h-1 do
write("|")
term.setCursorPos(w, i+2)
i = i + 1
end

term.setCursorPos(math.ceil(w / 2)-3, h-4)
write("1 / 3")
term.setCursorPos(math.ceil(w / 2)-5, h-2)
write("[X] - Back")
end
function drawItem(pos, name)
    term.setCursorPos(math.ceil((w / 2) - (#name / 2)), math.ceil((h / 2) + pos))
    write(name)
end
function drawProgs()
    drawItem(-7, "Programs")
for i = 1, #PROGRAMS do
drawItem(-7+1+i, ((nProg == i) and "[ "..PROGRAMS[i].." ]") or PROGRAMS[i])
end
end


-- System

drawBorder()
drawProgs()

while true do
local event, key = os.pullEvent( "key" )
if key == keys.down then
nProg = nProg + 1
elseif key == keys.up then
nProg = nProg - 1
elseif key == keys.enter then
shell.run("SimpleOS/Data/Programs/"..PROGRAMS[nProg])
elseif key == keys.x then
shell.run("SimpleOS/System/Menu.lua")
break
end
if nProg > #PROGRAMS then
nProg = #PROGRAMS
elseif nProg < 1 then
nProg = 1
end
term.clear()
drawBorder()
drawProgs()
end

Lupus590

Sometimes is easier to use someone else's code. What you want is called pagination and I looked for a Lua implementation for it and found this.

https://github.com/phoebethewitch/Pagination.lua/blob/main/Pagination.lua

You should be able to use it in your code like this, so long as you download the file somewhere that require can find it. Basically, it splits one big table into several sub-tables such that each sub-table has a max number of entries equal to the page size.

local pagination = require("Pagination")

function drawProgs(page)
    drawItem(-7, "Programs")
    local pageHeight = 9 -- TODO: calculate from term.size()
    local pagedPrograms = pagination.Paginate(PROGRAMS, pageHeight)

    for i = 1, #pagedPrograms[page] do
drawItem(-7+1+i, ((nProg == i) and "[ "..pagedPrograms[page][i].." ]") or pagedPrograms[page][i])
    end
end


Like the TODO comment says, you'll probably want to have the page size change if the screen height is different.

local function convertPagednProgToUnpaged(nProg, pageNumber)
    local pageHeight = 9 -- make sure this is the same as the one in drawPages, it might be good to make this variable outside of the functions

    return pageNumber * pageHeight + nProg
end

Of course, now nProg will be pointing to the wrong entry on any page other than the first, so you'll need to add to its value to account for the entries in the prior pages.

Mazepa

Thank you very much! I will try it.