From d381ac16937c505c3b58dbf9b168934352481db9 Mon Sep 17 00:00:00 2001 From: Max <33982882+maxboeer@users.noreply.github.com> Date: Mon, 1 Jun 2026 05:12:24 +0200 Subject: [PATCH] Implement page scrolling (seperate into runScrollableGrid) --- compcount.lua | 222 +++++++++++++++++++++++++++----------------------- 1 file changed, 119 insertions(+), 103 deletions(-) diff --git a/compcount.lua b/compcount.lua index a68dc22..5cf51e4 100644 --- a/compcount.lua +++ b/compcount.lua @@ -434,55 +434,9 @@ local function drawItem(img, cellX, cellY, count, offsetY) end end -local function drawPage(base_id) - local pageItems = getPageItems(base_id) - local defaultIcon = getFallbackIcon() - local backIcon = getBackButton() - local backWidth, backHeight = imageSize(backIcon) - local backX = SCREEN_WIDTH - backWidth + 1 - local pageItemIds = {} - local visibleItemCount = math.min(#pageItems, 9) - - for i = 1, visibleItemCount do - pageItemIds[i] = pageItems[i].id - end - - local function renderPage() - local itemCounts = getMeItemCounts(pageItemIds) - - frame.buffer:clear() - drawNfpScaled(frame.buffer, backIcon, (backX - 1) * 2 + 1, 1) - - for i = 1, visibleItemCount do - local item = pageItems[i] - local icon = getItemIcon(item) or defaultIcon - drawItem(icon, 4+(8+4)*((i-1)%3), 2+(5+1)*math.floor((i-1)/3), itemCounts[item.id] or 0) - end - - assertBufferValid(frame) - frame:drawBuffer() - end - - renderPage() - local refreshTimer = os.startTimer(5) - - while true do - local event, p1, x, y = os.pullEvent() - - if event == "timer" and p1 == refreshTimer then - renderPage() - refreshTimer = os.startTimer(5) - elseif event == "monitor_touch" and p1 == monName and x >= backX and x < backX + backWidth and y >= 1 and y <= backHeight then - drawOverview() - return - end - end -end - -drawOverview = function() - local items = getBaseItemIds() - local sortedItemIds = {} - local itemCounts = {} +local function runScrollableGrid(options) + local entries = {} + local counts = {} local visibleItemCount = 0 local totalRows = 0 local maxScrollRow = 0 @@ -543,25 +497,12 @@ drawOverview = function() end end - local function renderOverview() - itemCounts = getMeItemCounts(items) + local function refreshGridData() + entries, counts = options.getEntriesAndCounts() + end - for i = 1, #items do - sortedItemIds[i] = items[i] - end - - table.sort(sortedItemIds, function(a, b) - local countA = itemCounts[a] or 0 - local countB = itemCounts[b] or 0 - - if countA ~= countB then - return countA > countB - end - - return a < b - end) - - totalRows = math.ceil(#sortedItemIds / columns) + local function renderGrid() + totalRows = math.ceil(#entries / columns) maxScrollRow = math.max(0, totalRows - rowsPerView) currentScrollRow = clampScrollRow(currentScrollRow) targetScrollRow = clampScrollRow(targetScrollRow) @@ -569,27 +510,29 @@ drawOverview = function() local firstVisibleRow = math.floor(currentScrollRow) local rowOffsetPixels = -math.floor((currentScrollRow - firstVisibleRow) * rowStepPixels + 0.5) local firstVisibleIndex = firstVisibleRow * columns + 1 - local lastVisibleIndex = math.min(#sortedItemIds, (firstVisibleRow + rowsPerView + 1) * columns) + local lastVisibleIndex = math.min(#entries, (firstVisibleRow + rowsPerView + 1) * columns) frame.buffer:clear() + if options.drawChrome then + options.drawChrome() + end + for i = firstVisibleIndex, lastVisibleIndex do - local itemId = sortedItemIds[i] - local item = getItemById(itemId) - local icon = getItemIcon(item) or getFallbackIcon() + local entry = entries[i] local relativeIndex = i - firstVisibleIndex local col = relativeIndex % columns local row = math.floor(relativeIndex / columns) drawItem( - icon, + options.getIcon(entry), baseCellX + colStepCells * col, baseCellY + rowStepCells * row, - itemCounts[itemId] or 0, + counts[options.getId(entry)] or 0, rowOffsetPixels ) end - visibleItemCount = math.max(0, math.min(#sortedItemIds - firstVisibleRow * columns, rowsPerView * columns)) + visibleItemCount = math.max(0, math.min(#entries - firstVisibleRow * columns, rowsPerView * columns)) local upButtonY = cellToPixelY(1) local downButtonY = cellToPixelY(SCREEN_HEIGHT - scrollbarButtonHeight + 1) @@ -612,15 +555,17 @@ drawOverview = function() frame:drawBuffer() end - renderOverview() - refreshTimer = os.startTimer(30) + refreshGridData() + renderGrid() + refreshTimer = os.startTimer(options.refreshSeconds or 30) while true do local event, p1, x, y = os.pullEvent() if event == "timer" and p1 == refreshTimer then - renderOverview() - refreshTimer = os.startTimer(30) + refreshGridData() + renderGrid() + refreshTimer = os.startTimer(options.refreshSeconds or 30) scheduleAnimation() elseif event == "timer" and p1 == animationTimer then local delta = targetScrollRow - currentScrollRow @@ -646,9 +591,11 @@ drawOverview = function() end end - renderOverview() + renderGrid() elseif event == "monitor_touch" and p1 == monName then - if x >= scrollbarX and x < scrollbarX + scrollbarWidth then + if options.handleChromeTouch and options.handleChromeTouch(x, y) then + return + elseif x >= scrollbarX and x < scrollbarX + scrollbarWidth then if y <= scrollbarButtonHeight then scrollTo(targetScrollRow - 1) elseif y > SCREEN_HEIGHT - scrollbarButtonHeight then @@ -657,26 +604,14 @@ drawOverview = function() local touchPixelY = cellToPixelY(y) + 1 local thumbY, thumbHeight = getThumbMetrics() - if touchPixelY < thumbY then - if maxScrollRow > 0 then - local thumbTravel = scrollbarTrackPixelHeight - thumbHeight - local targetPixelY = math.max( - scrollbarTrackPixelY, - math.min(scrollbarTrackPixelY + thumbTravel, touchPixelY - math.floor(thumbHeight / 2)) - ) - local progress = (targetPixelY - scrollbarTrackPixelY) / math.max(1, thumbTravel) - scrollTo(progress * maxScrollRow) - end - elseif touchPixelY > thumbY + thumbHeight - 1 then - if maxScrollRow > 0 then - local thumbTravel = scrollbarTrackPixelHeight - thumbHeight - local targetPixelY = math.max( - scrollbarTrackPixelY, - math.min(scrollbarTrackPixelY + thumbTravel, touchPixelY - math.floor(thumbHeight / 2)) - ) - local progress = (targetPixelY - scrollbarTrackPixelY) / math.max(1, thumbTravel) - scrollTo(progress * maxScrollRow) - end + if (touchPixelY < thumbY or touchPixelY > thumbY + thumbHeight - 1) and maxScrollRow > 0 then + local thumbTravel = scrollbarTrackPixelHeight - thumbHeight + local targetPixelY = math.max( + scrollbarTrackPixelY, + math.min(scrollbarTrackPixelY + thumbTravel, touchPixelY - math.floor(thumbHeight / 2)) + ) + local progress = (targetPixelY - scrollbarTrackPixelY) / math.max(1, thumbTravel) + scrollTo(progress * maxScrollRow) end end else @@ -689,9 +624,10 @@ drawOverview = function() if col >= 0 and col < columns and row >= 0 and row < rowsPerView + 1 then local index = (firstVisibleRow + row) * columns + col + 1 - if index >= 1 and index <= #sortedItemIds and index <= firstVisibleRow * columns + visibleItemCount + columns then - drawPage(sortedItemIds[index]) - return + if index >= 1 and index <= #entries and index <= firstVisibleRow * columns + visibleItemCount + columns then + if options.onSelect(entries[index], index) then + return + end end end end @@ -699,6 +635,86 @@ drawOverview = function() end end +local function drawPage(base_id) + local pageItems = getPageItems(base_id) + local defaultIcon = getFallbackIcon() + local backIcon = getBackButton() + local backWidth, backHeight = imageSize(backIcon) + local backX = 1 + local pageItemIds = {} + + for i = 1, #pageItems do + pageItemIds[i] = pageItems[i].id + end + + runScrollableGrid({ + refreshSeconds = 5, + getEntriesAndCounts = function() + return pageItems, getMeItemCounts(pageItemIds) + end, + getId = function(entry) + return entry.id + end, + getIcon = function(entry) + return getItemIcon(entry) or defaultIcon + end, + drawChrome = function() + drawNfpScaled(frame.buffer, backIcon, cellToPixelX(backX), 1) + end, + handleChromeTouch = function(x, y) + if x >= backX and x < backX + backWidth and y >= 1 and y <= backHeight then + drawOverview() + return true + end + + return false + end, + onSelect = function() + return false + end, + }) +end + +drawOverview = function() + local items = getBaseItemIds() + local defaultIcon = getFallbackIcon() + + runScrollableGrid({ + refreshSeconds = 30, + getEntriesAndCounts = function() + local itemCounts = getMeItemCounts(items) + local sortedItemIds = {} + + for i = 1, #items do + sortedItemIds[i] = items[i] + end + + table.sort(sortedItemIds, function(a, b) + local countA = itemCounts[a] or 0 + local countB = itemCounts[b] or 0 + + if countA ~= countB then + return countA > countB + end + + return a < b + end) + + return sortedItemIds, itemCounts + end, + getId = function(entry) + return entry + end, + getIcon = function(entry) + return getItemIcon(getItemById(entry)) or defaultIcon + end, + onSelect = function(entry) + drawPage(entry) + return true + end, + }) +end + drawOverview() term.redirect(oldTerm)