simplified grid implementation

This commit is contained in:
Michael Freno
2025-10-11 21:05:24 -04:00
parent 2c68260340
commit 3df05d561f
5 changed files with 444 additions and 1153 deletions

View File

@@ -1,5 +1,5 @@
-- Grid Layout Tests
-- Tests for CSS Grid layout functionality
-- Tests for simplified grid layout functionality
package.path = package.path .. ";?.lua"
@@ -22,37 +22,6 @@ function TestGridLayout:tearDown()
Gui.destroy()
end
-- ====================
-- Track Parsing Tests (via grid behavior)
-- ====================
function TestGridLayout:test_grid_accepts_various_track_formats()
-- Test that grid accepts various track size formats without errors
local grid1 = Gui.new({
x = 0,
y = 0,
width = 600,
height = 400,
positioning = enums.Positioning.GRID,
gridTemplateColumns = "100px 2fr 50%",
gridTemplateRows = "auto 1fr",
})
lu.assertNotNil(grid1)
local grid2 = Gui.new({
x = 0,
y = 0,
width = 600,
height = 400,
positioning = enums.Positioning.GRID,
gridTemplateColumns = "repeat(3, 1fr)",
gridTemplateRows = "repeat(2, 100px)",
})
lu.assertNotNil(grid2)
Gui.destroy()
end
-- ====================
-- Basic Grid Layout Tests
-- ====================
@@ -64,13 +33,13 @@ function TestGridLayout:test_simple_grid_creation()
width = 600,
height = 400,
positioning = enums.Positioning.GRID,
gridTemplateColumns = "1fr 1fr 1fr",
gridTemplateRows = "1fr 1fr",
gridRows = 2,
gridColumns = 3,
})
lu.assertEquals(grid.positioning, enums.Positioning.GRID)
lu.assertEquals(grid.gridTemplateColumns, "1fr 1fr 1fr")
lu.assertEquals(grid.gridTemplateRows, "1fr 1fr")
lu.assertEquals(grid.gridRows, 2)
lu.assertEquals(grid.gridColumns, 3)
end
function TestGridLayout:test_grid_with_gaps()
@@ -80,8 +49,8 @@ function TestGridLayout:test_grid_with_gaps()
width = 600,
height = 400,
positioning = enums.Positioning.GRID,
gridTemplateColumns = "1fr 1fr",
gridTemplateRows = "1fr 1fr",
gridRows = 2,
gridColumns = 2,
columnGap = 10,
rowGap = 20,
})
@@ -97,8 +66,8 @@ function TestGridLayout:test_grid_auto_placement()
width = 300,
height = 200,
positioning = enums.Positioning.GRID,
gridTemplateColumns = "100px 100px 100px",
gridTemplateRows = "100px 100px",
gridRows = 2,
gridColumns = 3,
columnGap = 0,
rowGap = 0,
padding = { horizontal = 0, vertical = 0 },
@@ -127,75 +96,15 @@ function TestGridLayout:test_grid_auto_placement()
lu.assertAlmostEquals(items[4].y, 100, 1)
end
function TestGridLayout:test_grid_explicit_placement()
function TestGridLayout:test_grid_equal_distribution()
local grid = Gui.new({
x = 0,
y = 0,
width = 300,
height = 200,
positioning = enums.Positioning.GRID,
gridTemplateColumns = "100px 100px 100px",
gridTemplateRows = "100px 100px",
columnGap = 0,
rowGap = 0,
padding = { horizontal = 0, vertical = 0 },
})
-- Place item at column 2, row 2
local item = Gui.new({
parent = grid,
gridColumn = 2,
gridRow = 2,
width = 50,
height = 50,
})
-- Should be at position (100, 100)
lu.assertAlmostEquals(item.x, 100, 1)
lu.assertAlmostEquals(item.y, 100, 1)
end
function TestGridLayout:test_grid_spanning()
local grid = Gui.new({
x = 0,
y = 0,
width = 300,
height = 200,
positioning = enums.Positioning.GRID,
gridTemplateColumns = "100px 100px 100px",
gridTemplateRows = "100px 100px",
columnGap = 0,
rowGap = 0,
padding = { horizontal = 0, vertical = 0 },
})
-- Item spanning columns 1-3
local item = Gui.new({
parent = grid,
gridColumn = "1 / 4",
gridRow = 1,
width = 50,
height = 50,
})
-- Should start at x=0 and span 300px (3 columns)
lu.assertAlmostEquals(item.x, 0, 1)
lu.assertAlmostEquals(item.width, 300, 1)
end
-- ====================
-- Track Sizing Tests
-- ====================
function TestGridLayout:test_fr_unit_distribution()
local grid = Gui.new({
x = 0,
y = 0,
width = 300,
height = 200,
positioning = enums.Positioning.GRID,
gridTemplateColumns = "1fr 2fr",
gridTemplateRows = "1fr",
gridRows = 2,
gridColumns = 2,
columnGap = 0,
rowGap = 0,
padding = { horizontal = 0, vertical = 0 },
@@ -203,105 +112,52 @@ function TestGridLayout:test_fr_unit_distribution()
local item1 = Gui.new({
parent = grid,
gridColumn = 1,
gridRow = 1,
width = 50,
height = 50,
})
local item2 = Gui.new({
parent = grid,
gridColumn = 2,
gridRow = 1,
width = 50,
height = 50,
})
-- First column should be 100px (1fr), second should be 200px (2fr)
lu.assertAlmostEquals(item1.x, 0, 1)
lu.assertAlmostEquals(item2.x, 100, 1)
lu.assertAlmostEquals(item1.width, 100, 1)
lu.assertAlmostEquals(item2.width, 200, 1)
-- Each cell should be 150x100 (300/2 x 200/2)
lu.assertAlmostEquals(item1.width, 150, 1)
lu.assertAlmostEquals(item1.height, 100, 1)
lu.assertAlmostEquals(item2.x, 150, 1)
lu.assertAlmostEquals(item2.width, 150, 1)
end
function TestGridLayout:test_mixed_units()
function TestGridLayout:test_grid_stretch_behavior()
local grid = Gui.new({
x = 0,
y = 0,
width = 400,
height = 200,
positioning = enums.Positioning.GRID,
gridTemplateColumns = "100px 1fr 2fr",
gridTemplateRows = "1fr",
gridRows = 1,
gridColumns = 3,
columnGap = 0,
rowGap = 0,
padding = { horizontal = 0, vertical = 0 },
})
local item1 = Gui.new({ parent = grid, gridColumn = 1, gridRow = 1, width = 50, height = 50 })
local item2 = Gui.new({ parent = grid, gridColumn = 2, gridRow = 1, width = 50, height = 50 })
local item3 = Gui.new({ parent = grid, gridColumn = 3, gridRow = 1, width = 50, height = 50 })
local item1 = Gui.new({ parent = grid, width = 50, height = 50 })
local item2 = Gui.new({ parent = grid, width = 50, height = 50 })
local item3 = Gui.new({ parent = grid, width = 50, height = 50 })
-- First column: 100px (fixed)
-- Remaining 300px divided as 1fr (100px) and 2fr (200px)
lu.assertAlmostEquals(item1.width, 100, 1)
lu.assertAlmostEquals(item2.width, 100, 1)
lu.assertAlmostEquals(item3.width, 200, 1)
end
function TestGridLayout:test_percentage_columns()
local grid = Gui.new({
x = 0,
y = 0,
width = 400,
height = 200,
positioning = enums.Positioning.GRID,
gridTemplateColumns = "25% 50% 25%",
gridTemplateRows = "1fr",
columnGap = 0,
rowGap = 0,
padding = { horizontal = 0, vertical = 0 },
})
local item1 = Gui.new({ parent = grid, gridColumn = 1, gridRow = 1, width = 50, height = 50 })
local item2 = Gui.new({ parent = grid, gridColumn = 2, gridRow = 1, width = 50, height = 50 })
local item3 = Gui.new({ parent = grid, gridColumn = 3, gridRow = 1, width = 50, height = 50 })
lu.assertAlmostEquals(item1.width, 100, 1) -- 25% of 400
lu.assertAlmostEquals(item2.width, 200, 1) -- 50% of 400
lu.assertAlmostEquals(item3.width, 100, 1) -- 25% of 400
-- Each cell should be ~133.33px wide (400/3)
-- Items should stretch to fill cells
lu.assertAlmostEquals(item1.width, 133.33, 1)
lu.assertAlmostEquals(item2.width, 133.33, 1)
lu.assertAlmostEquals(item3.width, 133.33, 1)
end
-- ====================
-- Alignment Tests
-- ====================
function TestGridLayout:test_justify_items_stretch()
local grid = Gui.new({
x = 0,
y = 0,
width = 300,
height = 200,
positioning = enums.Positioning.GRID,
gridTemplateColumns = "100px 100px 100px",
gridTemplateRows = "100px",
justifyItems = enums.GridJustifyItems.STRETCH,
columnGap = 0,
rowGap = 0,
padding = { horizontal = 0, vertical = 0 },
})
local item = Gui.new({
parent = grid,
gridColumn = 1,
gridRow = 1,
height = 50,
})
-- Item should stretch to fill cell width
lu.assertAlmostEquals(item.width, 100, 1)
end
function TestGridLayout:test_align_items_stretch()
local grid = Gui.new({
x = 0,
@@ -309,8 +165,8 @@ function TestGridLayout:test_align_items_stretch()
width = 300,
height = 200,
positioning = enums.Positioning.GRID,
gridTemplateColumns = "100px",
gridTemplateRows = "100px 100px",
gridRows = 2,
gridColumns = 1,
alignItems = enums.AlignItems.STRETCH,
columnGap = 0,
rowGap = 0,
@@ -319,12 +175,10 @@ function TestGridLayout:test_align_items_stretch()
local item = Gui.new({
parent = grid,
gridColumn = 1,
gridRow = 1,
width = 50,
})
-- Item should stretch to fill cell height
-- Item should stretch to fill cell height (200/2 = 100)
lu.assertAlmostEquals(item.height, 100, 1)
end
@@ -339,17 +193,18 @@ function TestGridLayout:test_column_gap()
width = 320,
height = 100,
positioning = enums.Positioning.GRID,
gridTemplateColumns = "100px 100px 100px",
gridTemplateRows = "100px",
gridRows = 1,
gridColumns = 3,
columnGap = 10,
rowGap = 0,
padding = { horizontal = 0, vertical = 0 },
})
local item1 = Gui.new({ parent = grid, gridColumn = 1, gridRow = 1, width = 50, height = 50 })
local item2 = Gui.new({ parent = grid, gridColumn = 2, gridRow = 1, width = 50, height = 50 })
local item3 = Gui.new({ parent = grid, gridColumn = 3, gridRow = 1, width = 50, height = 50 })
local item1 = Gui.new({ parent = grid, width = 50, height = 50 })
local item2 = Gui.new({ parent = grid, width = 50, height = 50 })
local item3 = Gui.new({ parent = grid, width = 50, height = 50 })
-- Total width: 320, gaps: 2*10=20, available: 300, per cell: 100
lu.assertAlmostEquals(item1.x, 0, 1)
lu.assertAlmostEquals(item2.x, 110, 1) -- 100 + 10 gap
lu.assertAlmostEquals(item3.x, 220, 1) -- 100 + 10 + 100 + 10
@@ -362,17 +217,18 @@ function TestGridLayout:test_row_gap()
width = 100,
height = 320,
positioning = enums.Positioning.GRID,
gridTemplateColumns = "100px",
gridTemplateRows = "100px 100px 100px",
gridRows = 3,
gridColumns = 1,
columnGap = 0,
rowGap = 10,
padding = { horizontal = 0, vertical = 0 },
})
local item1 = Gui.new({ parent = grid, gridColumn = 1, gridRow = 1, width = 50, height = 50 })
local item2 = Gui.new({ parent = grid, gridColumn = 1, gridRow = 2, width = 50, height = 50 })
local item3 = Gui.new({ parent = grid, gridColumn = 1, gridRow = 3, width = 50, height = 50 })
local item1 = Gui.new({ parent = grid, width = 50, height = 50 })
local item2 = Gui.new({ parent = grid, width = 50, height = 50 })
local item3 = Gui.new({ parent = grid, width = 50, height = 50 })
-- Total height: 320, gaps: 2*10=20, available: 300, per cell: 100
lu.assertAlmostEquals(item1.y, 0, 1)
lu.assertAlmostEquals(item2.y, 110, 1) -- 100 + 10 gap
lu.assertAlmostEquals(item3.y, 220, 1) -- 100 + 10 + 100 + 10
@@ -389,8 +245,8 @@ function TestGridLayout:test_nested_grids()
width = 400,
height = 400,
positioning = enums.Positioning.GRID,
gridTemplateColumns = "1fr 1fr",
gridTemplateRows = "1fr 1fr",
gridRows = 2,
gridColumns = 2,
columnGap = 0,
rowGap = 0,
padding = { horizontal = 0, vertical = 0 },
@@ -398,29 +254,92 @@ function TestGridLayout:test_nested_grids()
local innerGrid = Gui.new({
parent = outerGrid,
gridColumn = 1,
gridRow = 1,
positioning = enums.Positioning.GRID,
gridTemplateColumns = "1fr 1fr",
gridTemplateRows = "1fr 1fr",
gridRows = 2,
gridColumns = 2,
columnGap = 0,
rowGap = 0,
padding = { horizontal = 0, vertical = 0 },
})
local innerItem = Gui.new({
parent = innerGrid,
gridColumn = 2,
gridRow = 2,
-- Add items to inner grid
local item1 = Gui.new({ parent = innerGrid, width = 50, height = 50 })
local item2 = Gui.new({ parent = innerGrid, width = 50, height = 50 })
-- Inner grid should be stretched to fill outer grid cell (200x200)
lu.assertAlmostEquals(innerGrid.width, 200, 1)
lu.assertAlmostEquals(innerGrid.height, 200, 1)
-- Items in inner grid should be positioned correctly
-- Each cell in inner grid is 100x100
lu.assertAlmostEquals(item1.x, 0, 1)
lu.assertAlmostEquals(item1.y, 0, 1)
lu.assertAlmostEquals(item2.x, 100, 1)
lu.assertAlmostEquals(item2.y, 0, 1)
end
-- ====================
-- Edge Cases
-- ====================
function TestGridLayout:test_more_items_than_cells()
local grid = Gui.new({
x = 0,
y = 0,
width = 200,
height = 200,
positioning = enums.Positioning.GRID,
gridRows = 2,
gridColumns = 2,
columnGap = 0,
rowGap = 0,
padding = { horizontal = 0, vertical = 0 },
})
local items = {}
for i = 1, 6 do
items[i] = Gui.new({
parent = grid,
width = 50,
height = 50,
})
end
-- First 4 items should be positioned
lu.assertAlmostEquals(items[1].x, 0, 1)
lu.assertAlmostEquals(items[4].x, 100, 1)
lu.assertAlmostEquals(items[4].y, 100, 1)
-- Items 5 and 6 should not be laid out (remain at parent position)
-- This is acceptable behavior - they're just not visible in the grid
end
function TestGridLayout:test_single_cell_grid()
local grid = Gui.new({
x = 0,
y = 0,
width = 100,
height = 100,
positioning = enums.Positioning.GRID,
gridRows = 1,
gridColumns = 1,
columnGap = 0,
rowGap = 0,
padding = { horizontal = 0, vertical = 0 },
})
local item = Gui.new({
parent = grid,
width = 50,
height = 50,
})
-- Inner grid should be in top-left quadrant (200x200)
-- Inner item should be in bottom-right of that (at 100, 100 relative to inner grid)
lu.assertAlmostEquals(innerItem.x, 100, 1)
lu.assertAlmostEquals(innerItem.y, 100, 1)
-- Item should stretch to fill the entire grid
lu.assertAlmostEquals(item.x, 0, 1)
lu.assertAlmostEquals(item.y, 0, 1)
lu.assertAlmostEquals(item.width, 100, 1)
lu.assertAlmostEquals(item.height, 100, 1)
end
print("Running Grid Layout Tests...")
print("Running Simplified Grid Layout Tests...")
os.exit(lu.LuaUnit.run())