mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-19 12:15:31 +02:00
scroll list
This commit is contained in:
+45
-12
@@ -14,10 +14,9 @@
|
|||||||
-- height, and flex-shrink compressing text until it overlapped.
|
-- height, and flex-shrink compressing text until it overlapped.
|
||||||
--
|
--
|
||||||
-- THE RULES THIS FILE FOLLOWS:
|
-- THE RULES THIS FILE FOLLOWS:
|
||||||
-- * NO SCROLLING. Every list paginates (Kit.pager). Rows per page come
|
-- * Lists paginate (Kit.pager). The installed-mod list also scrolls inside
|
||||||
-- from the real viewport height, so a tall window shows more and a phone
|
-- its viewport, so each of its pages can hold at least ten entries without
|
||||||
-- shows fewer -- but a page's row count is bounded either way, which is
|
-- requiring a tall window. Pages still bound how many mod rows we visit.
|
||||||
-- what makes a 500-mod index cost the same as a 10-mod one.
|
|
||||||
-- * Every click handler only QUEUES work (imp._uiActions); update() drains
|
-- * Every click handler only QUEUES work (imp._uiActions); update() drains
|
||||||
-- the queue, so an action that tears the view down (Play, Edit save)
|
-- the queue, so an action that tears the view down (Play, Edit save)
|
||||||
-- never runs inside the frame that dispatched it.
|
-- never runs inside the frame that dispatched it.
|
||||||
@@ -46,9 +45,17 @@ local COMMUNITY_URL = "https://bois.icu"
|
|||||||
local ACT_DEDUP = 0.35
|
local ACT_DEDUP = 0.35
|
||||||
-- Finger travel past this (px) is a drag, not a tap.
|
-- Finger travel past this (px) is a drag, not a tap.
|
||||||
local TAP_SLOP2 = 16 * 16
|
local TAP_SLOP2 = 16 * 16
|
||||||
|
-- Installed mods should not turn into a one- or two-item pager on a compact
|
||||||
|
-- display. Keep a useful page size, then let the list viewport scroll.
|
||||||
|
local MIN_MODS_PER_PAGE = 10
|
||||||
|
|
||||||
local function clamp(v, lo, hi) return math.max(lo, math.min(hi, v)) end
|
local function clamp(v, lo, hi) return math.max(lo, math.min(hi, v)) end
|
||||||
|
|
||||||
|
local function inRect(rect, x, y)
|
||||||
|
return rect ~= nil and x >= rect.x and x <= rect.x + rect.w
|
||||||
|
and y >= rect.y and y <= rect.y + rect.h
|
||||||
|
end
|
||||||
|
|
||||||
-- ------------------------------------------------------------- lifecycle
|
-- ------------------------------------------------------------- lifecycle
|
||||||
|
|
||||||
local function ensureState(imp)
|
local function ensureState(imp)
|
||||||
@@ -146,7 +153,10 @@ end
|
|||||||
function LauncherView.touchpressed(imp, id, x, y)
|
function LauncherView.touchpressed(imp, id, x, y)
|
||||||
if not imp._flex then return end
|
if not imp._flex then return end
|
||||||
imp._touchAt = imp._touchAt or {}
|
imp._touchAt = imp._touchAt or {}
|
||||||
imp._touchAt[tostring(id)] = { x = x, y = y }
|
imp._touchAt[tostring(id)] = {
|
||||||
|
x = x, y = y,
|
||||||
|
modsList = (imp._modScrollMax or 0) > 0 and inRect(imp._modListRect, x, y),
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
function LauncherView.touchmoved(imp, id, x, y)
|
function LauncherView.touchmoved(imp, id, x, y)
|
||||||
@@ -157,8 +167,14 @@ function LauncherView.touchmoved(imp, id, x, y)
|
|||||||
if ddx * ddx + ddy * ddy > TAP_SLOP2 then
|
if ddx * ddx + ddy * ddy > TAP_SLOP2 then
|
||||||
start.dragged = true
|
start.dragged = true
|
||||||
end
|
end
|
||||||
-- Short-window mode: a vertical drag scrolls the page (draw() clamps).
|
-- A drag that began in the installed-mod viewport scrolls that page's
|
||||||
if start.dragged and (imp._pageScrollMax or 0) > 0 then
|
-- rows. Its pager remains available for moving to the next ten-plus
|
||||||
|
-- entries; a drag elsewhere keeps the normal short-window page scroll.
|
||||||
|
if start.dragged and start.modsList then
|
||||||
|
local last = start.lastY or start.y
|
||||||
|
imp.modScroll = clamp((imp.modScroll or 0) - (y - last), 0,
|
||||||
|
imp._modScrollMax or 0)
|
||||||
|
elseif start.dragged and (imp._pageScrollMax or 0) > 0 then
|
||||||
local last = start.lastY or start.y
|
local last = start.lastY or start.y
|
||||||
imp._pageScroll = (imp._pageScroll or 0) - (y - last)
|
imp._pageScroll = (imp._pageScroll or 0) - (y - last)
|
||||||
end
|
end
|
||||||
@@ -1441,6 +1457,7 @@ local function buildModsPanel(imp, x, y, w, availH, m)
|
|||||||
cy = cy + buildModScopeRow(imp, x, cy, w, m)
|
cy = cy + buildModScopeRow(imp, x, cy, w, m)
|
||||||
|
|
||||||
if #mods == 0 then
|
if #mods == 0 then
|
||||||
|
imp.modScroll, imp._modScrollMax, imp._modListRect = 0, 0, nil
|
||||||
Kit.emptyBox(x, cy, w, math.floor(110 * m.s), imp:_modsEmptyHint())
|
Kit.emptyBox(x, cy, w, math.floor(110 * m.s), imp:_modsEmptyHint())
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@@ -1492,16 +1509,30 @@ local function buildModsPanel(imp, x, y, w, availH, m)
|
|||||||
+ math.floor(8 * m.s)
|
+ math.floor(8 * m.s)
|
||||||
local pagerH = math.max(Kit.tapMin(), math.floor(30 * m.s))
|
local pagerH = math.max(Kit.tapMin(), math.floor(30 * m.s))
|
||||||
local listH = availH - (cy - y) - pagerH - gap
|
local listH = availH - (cy - y) - pagerH - gap
|
||||||
local perPage = Kit.rowsThatFit(listH, rowH, gap, 1, 20)
|
local perPage = Kit.rowsThatFit(listH, rowH, gap, MIN_MODS_PER_PAGE, 20)
|
||||||
local first, last, cur, pages = Kit.pageBounds(page(imp, "mods"), #mods, perPage)
|
local first, last, cur, pages = Kit.pageBounds(page(imp, "mods"), #mods, perPage)
|
||||||
setPage(imp, "mods", cur)
|
setPage(imp, "mods", cur)
|
||||||
local listTop = cy
|
local listTop = cy
|
||||||
setPage(imp, "mods",
|
local shown = math.max(0, last - first + 1)
|
||||||
Kit.wheelPage(x, listTop, w, listH, cur, #mods, perPage))
|
local contentH = shown * rowH + math.max(0, shown - 1) * gap
|
||||||
|
local scrollMax = math.max(0, contentH - listH)
|
||||||
|
local scroll = clamp(imp.modScroll or 0, 0, scrollMax)
|
||||||
|
imp._modListRect = { x = x, y = listTop, w = w, h = listH }
|
||||||
|
imp._modScrollMax = scrollMax
|
||||||
|
if scrollMax > 0 and (Kit.wheelY or 0) ~= 0 and Kit.hit(x, listTop, w, listH) then
|
||||||
|
scroll = clamp(scroll - Kit.wheelY * math.floor(48 * m.s), 0, scrollMax)
|
||||||
|
Kit.wheelY = 0
|
||||||
|
elseif scrollMax == 0 then
|
||||||
|
local wheelPage = Kit.wheelPage(x, listTop, w, listH, cur, #mods, perPage)
|
||||||
|
if wheelPage ~= cur then imp.modScroll = 0 end
|
||||||
|
setPage(imp, "mods", wheelPage)
|
||||||
|
end
|
||||||
|
imp.modScroll = scroll
|
||||||
|
|
||||||
|
Kit.pushClip(x, listTop, w, listH)
|
||||||
for i = first, last do
|
for i = first, last do
|
||||||
local mod = mods[i]
|
local mod = mods[i]
|
||||||
local ry = listTop + (i - first) * (rowH + gap)
|
local ry = listTop + (i - first) * (rowH + gap) - scroll
|
||||||
local rowKey = "mod-row-" .. mod.id
|
local rowKey = "mod-row-" .. mod.id
|
||||||
-- The whole row is the control: it opens the per-mod actions popup
|
-- The whole row is the control: it opens the per-mod actions popup
|
||||||
-- (update / versions / delete moved there). Only the enable toggle
|
-- (update / versions / delete moved there). Only the enable toggle
|
||||||
@@ -1600,9 +1631,11 @@ local function buildModsPanel(imp, x, y, w, availH, m)
|
|||||||
px, ly, PAL.detail)
|
px, ly, PAL.detail)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
Kit.popClip()
|
||||||
|
|
||||||
local pagerY = listTop + (last - first + 1) * (rowH + gap)
|
local pagerY = listTop + listH + gap
|
||||||
local newPage = Kit.pager(x, pagerY, w, cur, #mods, perPage, "mods")
|
local newPage = Kit.pager(x, pagerY, w, cur, #mods, perPage, "mods")
|
||||||
|
if newPage ~= cur then imp.modScroll = 0 end
|
||||||
setPage(imp, "mods", newPage)
|
setPage(imp, "mods", newPage)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -1228,8 +1228,8 @@ function RomImporter.new(onComplete, opts)
|
|||||||
saveNotice = {},
|
saveNotice = {},
|
||||||
-- MODS panel state (pass 3): mods is the cached LauncherMods.list() array
|
-- MODS panel state (pass 3): mods is the cached LauncherMods.list() array
|
||||||
-- (refreshed lazily on first draw and after any toggle/install/delete);
|
-- (refreshed lazily on first draw and after any toggle/install/delete);
|
||||||
-- modScroll is the list scroll offset (px, clamped in draw); modNotice is
|
-- modScroll is the current paged list's inner scroll offset (px, clamped
|
||||||
-- the last install/delete result { ok, text } shown as a line above the list.
|
-- in draw); modNotice is the last install/delete result { ok, text }.
|
||||||
mods = nil, modScroll = 0, modNotice = nil,
|
mods = nil, modScroll = 0, modNotice = nil,
|
||||||
-- Which game the MODS panel is answering for (a GameVersion id, nil =
|
-- Which game the MODS panel is answering for (a GameVersion id, nil =
|
||||||
-- every game). Rows resolve their enable-state and their "runs here"
|
-- every game). Rows resolve their enable-state and their "runs here"
|
||||||
|
|||||||
Reference in New Issue
Block a user