scrolling improvements

This commit is contained in:
Michael Freno
2025-12-05 19:49:57 -05:00
parent c59f7c5661
commit f4dc92907c
10 changed files with 619 additions and 52 deletions

View File

@@ -1302,6 +1302,166 @@ function TestFlexLoveUnhappyPaths:testImmediateModeFrameEdgeCases()
luaunit.assertTrue(true)
end
-- Test: scrollSpeed prop is properly passed to ScrollManager in immediate mode
function TestFlexLove:testScrollSpeedInImmediateMode()
FlexLove.setMode("immediate")
FlexLove.beginFrame()
local element = FlexLove.new({
id = "scrollableElement",
width = 200,
height = 200,
overflow = "auto",
scrollSpeed = 75, -- Custom scroll speed
})
-- Add children to make it scrollable
for i = 1, 10 do
FlexLove.new({
parent = element,
width = 180,
height = 50,
})
end
FlexLove.endFrame()
-- Verify scrollSpeed was set correctly
luaunit.assertEquals(element.scrollSpeed, 75)
luaunit.assertNotNil(element._scrollManager)
luaunit.assertEquals(element._scrollManager.scrollSpeed, 75)
-- Test another frame to ensure scrollSpeed persists
FlexLove.beginFrame()
local element2 = FlexLove.new({
id = "scrollableElement",
width = 200,
height = 200,
overflow = "auto",
scrollSpeed = 75,
})
for i = 1, 10 do
FlexLove.new({
parent = element2,
width = 180,
height = 50,
})
end
FlexLove.endFrame()
-- Verify scrollSpeed is still correct after recreating element
luaunit.assertEquals(element2.scrollSpeed, 75)
luaunit.assertEquals(element2._scrollManager.scrollSpeed, 75)
end
-- Test: smoothScrollEnabled prop is properly passed to ScrollManager
function TestFlexLove:testSmoothScrollEnabledProp()
FlexLove.setMode("immediate")
FlexLove.beginFrame()
local element = FlexLove.new({
id = "smoothScrollElement",
width = 200,
height = 200,
overflow = "auto",
smoothScrollEnabled = true,
})
for i = 1, 10 do
FlexLove.new({
parent = element,
width = 180,
height = 50,
})
end
FlexLove.endFrame()
-- Verify smoothScrollEnabled was set correctly
luaunit.assertNotNil(element._scrollManager)
luaunit.assertTrue(element._scrollManager.smoothScrollEnabled)
end
-- Test: scrollSpeed must be provided every frame in immediate mode
function TestFlexLove:testScrollSpeedMustBeProvidedEveryFrame()
FlexLove.setMode("immediate")
-- Frame 1: Set custom scrollSpeed
FlexLove.beginFrame()
local element1 = FlexLove.new({
id = "scrollSpeedTest",
width = 200,
height = 200,
overflow = "auto",
scrollSpeed = 50,
})
for i = 1, 10 do
FlexLove.new({ parent = element1, width = 180, height = 50 })
end
FlexLove.endFrame()
luaunit.assertEquals(element1._scrollManager.scrollSpeed, 50)
-- Frame 2: Forget to provide scrollSpeed (should default to 20)
FlexLove.beginFrame()
local element2 = FlexLove.new({
id = "scrollSpeedTest",
width = 200,
height = 200,
overflow = "auto",
-- scrollSpeed NOT provided - will default to 20
})
for i = 1, 10 do
FlexLove.new({ parent = element2, width = 180, height = 50 })
end
FlexLove.endFrame()
-- In immediate mode, props must be provided every frame
luaunit.assertEquals(element2._scrollManager.scrollSpeed, 20)
end
-- Test: smooth scrolling actually interpolates scroll position
function TestFlexLove:testSmoothScrollingInterpolation()
FlexLove.setMode("retained")
local element = FlexLove.new({
width = 200,
height = 200,
overflow = "auto",
smoothScrollEnabled = true,
})
for i = 1, 20 do
FlexLove.new({
parent = element,
width = 180,
height = 50,
})
end
-- Manually set overflow state (normally done by layout)
element._scrollManager._overflowY = true
element._scrollManager._maxScrollY = 800 -- 20 * 50 - 200
-- Trigger wheel scroll
element:_handleWheelScroll(0, -1) -- Scroll down
-- Should set target, not immediate scroll
luaunit.assertNotNil(element._scrollManager._targetScrollY)
local initialScroll = element._scrollManager._scrollY
local targetScroll = element._scrollManager._targetScrollY
-- Initial scroll should be 0, target should be scrollSpeed (default 20)
luaunit.assertEquals(initialScroll, 0)
luaunit.assertEquals(targetScroll, 20)
-- Update should interpolate towards target
element:update(0.016) -- One frame at 60fps
local afterUpdate = element._scrollManager._scrollY
-- Scroll position should have moved towards target
luaunit.assertTrue(afterUpdate > initialScroll)
luaunit.assertTrue(afterUpdate <= targetScroll)
end
if not _G.RUNNING_ALL_TESTS then
os.exit(luaunit.LuaUnit.run())
end