pretty good
This commit is contained in:
56
FlexLove.lua
56
FlexLove.lua
@@ -40,6 +40,7 @@ enums.TextAlign = {
|
|||||||
--- @enum Positioning
|
--- @enum Positioning
|
||||||
enums.Positioning = {
|
enums.Positioning = {
|
||||||
ABSOLUTE = "absolute",
|
ABSOLUTE = "absolute",
|
||||||
|
RELATIVE = "relative",
|
||||||
FLEX = "flex",
|
FLEX = "flex",
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -743,7 +744,7 @@ function Element.new(props)
|
|||||||
self._originalPositioning = props.positioning
|
self._originalPositioning = props.positioning
|
||||||
self._explicitlyAbsolute = (props.positioning == Positioning.ABSOLUTE)
|
self._explicitlyAbsolute = (props.positioning == Positioning.ABSOLUTE)
|
||||||
else
|
else
|
||||||
self.positioning = Positioning.ABSOLUTE
|
self.positioning = Positioning.RELATIVE
|
||||||
self._originalPositioning = nil -- No explicit positioning
|
self._originalPositioning = nil -- No explicit positioning
|
||||||
self._explicitlyAbsolute = false
|
self._explicitlyAbsolute = false
|
||||||
end
|
end
|
||||||
@@ -758,13 +759,13 @@ function Element.new(props)
|
|||||||
self._explicitlyAbsolute = false
|
self._explicitlyAbsolute = false
|
||||||
else
|
else
|
||||||
-- Default: children in flex containers participate in flex layout
|
-- Default: children in flex containers participate in flex layout
|
||||||
-- children in absolute containers default to absolute
|
-- children in other containers default to relative
|
||||||
if self.parent.positioning == Positioning.FLEX then
|
if self.parent.positioning == Positioning.FLEX then
|
||||||
self.positioning = Positioning.ABSOLUTE -- They are positioned BY flex, not AS flex
|
self.positioning = Positioning.ABSOLUTE -- They are positioned BY flex, not AS flex
|
||||||
self._explicitlyAbsolute = false -- Participate in parent's flex layout
|
self._explicitlyAbsolute = false -- Participate in parent's flex layout
|
||||||
else
|
else
|
||||||
self.positioning = Positioning.ABSOLUTE
|
self.positioning = Positioning.RELATIVE
|
||||||
self._explicitlyAbsolute = false -- Default for absolute containers
|
self._explicitlyAbsolute = false -- Default for other containers
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -803,6 +804,44 @@ function Element.new(props)
|
|||||||
end
|
end
|
||||||
|
|
||||||
self.z = props.z or 0
|
self.z = props.z or 0
|
||||||
|
elseif self.positioning == Positioning.RELATIVE then
|
||||||
|
-- Relative positioning: position relative to parent's position
|
||||||
|
local baseX = self.parent.x
|
||||||
|
local baseY = self.parent.y
|
||||||
|
|
||||||
|
if props.x then
|
||||||
|
if type(props.x) == "string" then
|
||||||
|
local value, unit = Units.parse(props.x)
|
||||||
|
self.units.x = { value = value, unit = unit }
|
||||||
|
local parentWidth = self.parent.width
|
||||||
|
local offsetX = Units.resolve(value, unit, viewportWidth, viewportHeight, parentWidth)
|
||||||
|
self.x = baseX + offsetX
|
||||||
|
else
|
||||||
|
self.x = baseX + props.x
|
||||||
|
self.units.x = { value = props.x, unit = "px" }
|
||||||
|
end
|
||||||
|
else
|
||||||
|
self.x = baseX
|
||||||
|
self.units.x = { value = 0, unit = "px" }
|
||||||
|
end
|
||||||
|
|
||||||
|
if props.y then
|
||||||
|
if type(props.y) == "string" then
|
||||||
|
local value, unit = Units.parse(props.y)
|
||||||
|
self.units.y = { value = value, unit = unit }
|
||||||
|
local parentHeight = self.parent.height
|
||||||
|
local offsetY = Units.resolve(value, unit, viewportWidth, viewportHeight, parentHeight)
|
||||||
|
self.y = baseY + offsetY
|
||||||
|
else
|
||||||
|
self.y = baseY + props.y
|
||||||
|
self.units.y = { value = props.y, unit = "px" }
|
||||||
|
end
|
||||||
|
else
|
||||||
|
self.y = baseY
|
||||||
|
self.units.y = { value = 0, unit = "px" }
|
||||||
|
end
|
||||||
|
|
||||||
|
self.z = props.z or self.parent.z or 0
|
||||||
else
|
else
|
||||||
-- Children in flex containers start at parent position but will be repositioned by layoutChildren
|
-- Children in flex containers start at parent position but will be repositioned by layoutChildren
|
||||||
local baseX = self.parent.x
|
local baseX = self.parent.x
|
||||||
@@ -946,8 +985,8 @@ function Element:addChild(child)
|
|||||||
child.positioning = Positioning.ABSOLUTE -- They are positioned BY flex, not AS flex
|
child.positioning = Positioning.ABSOLUTE -- They are positioned BY flex, not AS flex
|
||||||
child._explicitlyAbsolute = false -- Participate in parent's flex layout
|
child._explicitlyAbsolute = false -- Participate in parent's flex layout
|
||||||
else
|
else
|
||||||
child.positioning = Positioning.ABSOLUTE
|
child.positioning = Positioning.RELATIVE
|
||||||
child._explicitlyAbsolute = false -- Default for absolute containers
|
child._explicitlyAbsolute = false -- Default for other containers
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
-- If child._originalPositioning is set, it means explicit positioning was provided
|
-- If child._originalPositioning is set, it means explicit positioning was provided
|
||||||
@@ -1020,7 +1059,10 @@ function Element:layoutChildren()
|
|||||||
-- Get flex children (children that participate in flex layout)
|
-- Get flex children (children that participate in flex layout)
|
||||||
local flexChildren = {}
|
local flexChildren = {}
|
||||||
for _, child in ipairs(self.children) do
|
for _, child in ipairs(self.children) do
|
||||||
local isFlexChild = not (child.positioning == Positioning.ABSOLUTE and child._explicitlyAbsolute)
|
-- Only flex positioned children or non-explicitly absolute children participate in flex layout
|
||||||
|
-- Relative positioned children maintain their own positioning
|
||||||
|
local isFlexChild = not (child.positioning == Positioning.ABSOLUTE and child._explicitlyAbsolute)
|
||||||
|
and child.positioning ~= Positioning.RELATIVE
|
||||||
if isFlexChild then
|
if isFlexChild then
|
||||||
table.insert(flexChildren, child)
|
table.insert(flexChildren, child)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -51,8 +51,8 @@ function TestAbsolutePositioningBasic:testDefaultAbsolutePositioning()
|
|||||||
h = 100,
|
h = 100,
|
||||||
})
|
})
|
||||||
|
|
||||||
-- Default should be absolute positioning
|
-- Default should be relative positioning
|
||||||
luaunit.assertEquals(elem.positioning, Positioning.ABSOLUTE)
|
luaunit.assertEquals(elem.positioning, Positioning.RELATIVE)
|
||||||
luaunit.assertEquals(elem.x, 50)
|
luaunit.assertEquals(elem.x, 50)
|
||||||
luaunit.assertEquals(elem.y, 75)
|
luaunit.assertEquals(elem.y, 75)
|
||||||
end
|
end
|
||||||
|
|||||||
199
testing/__tests__/13_relative_positioning_tests.lua
Normal file
199
testing/__tests__/13_relative_positioning_tests.lua
Normal file
@@ -0,0 +1,199 @@
|
|||||||
|
-- Test relative positioning functionality
|
||||||
|
package.path = package.path .. ";?.lua"
|
||||||
|
require("testing/loveStub")
|
||||||
|
local FlexLove = require("FlexLove")
|
||||||
|
local luaunit = require("testing/luaunit")
|
||||||
|
|
||||||
|
local Gui, enums = FlexLove.GUI, FlexLove.enums
|
||||||
|
local Color = FlexLove.Color
|
||||||
|
local Positioning = enums.Positioning
|
||||||
|
|
||||||
|
TestRelativePositioning = {}
|
||||||
|
|
||||||
|
-- Test 1: Basic relative positioning with pixel values
|
||||||
|
function TestRelativePositioning.testBasicRelativePositioning()
|
||||||
|
local parent = Gui.new({
|
||||||
|
x = 100,
|
||||||
|
y = 50,
|
||||||
|
w = 200,
|
||||||
|
h = 150,
|
||||||
|
positioning = "relative",
|
||||||
|
background = Color.new(0.2, 0.2, 0.2, 1.0),
|
||||||
|
})
|
||||||
|
|
||||||
|
local child = Gui.new({
|
||||||
|
parent = parent,
|
||||||
|
x = 20,
|
||||||
|
y = 30,
|
||||||
|
w = 50,
|
||||||
|
h = 40,
|
||||||
|
positioning = "relative",
|
||||||
|
background = Color.new(0.8, 0.2, 0.2, 1.0)
|
||||||
|
})
|
||||||
|
|
||||||
|
-- Child should be positioned relative to parent
|
||||||
|
luaunit.assertEquals(child.positioning, Positioning.RELATIVE)
|
||||||
|
luaunit.assertEquals(child.x, 120) -- parent.x (100) + offset (20)
|
||||||
|
luaunit.assertEquals(child.y, 80) -- parent.y (50) + offset (30)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Test 2: Relative positioning with percentage values
|
||||||
|
function TestRelativePositioning.testRelativePositioningPercentages()
|
||||||
|
local parent = Gui.new({
|
||||||
|
x = 50,
|
||||||
|
y = 100,
|
||||||
|
w = 200,
|
||||||
|
h = 100,
|
||||||
|
positioning = "relative",
|
||||||
|
background = Color.new(0.2, 0.2, 0.2, 1.0),
|
||||||
|
})
|
||||||
|
|
||||||
|
local child = Gui.new({
|
||||||
|
parent = parent,
|
||||||
|
x = "10%", -- 10% of parent width = 20px
|
||||||
|
y = "20%", -- 20% of parent height = 20px
|
||||||
|
w = 30,
|
||||||
|
h = 20,
|
||||||
|
positioning = "relative",
|
||||||
|
background = Color.new(0.8, 0.2, 0.2, 1.0)
|
||||||
|
})
|
||||||
|
|
||||||
|
-- Child should be positioned relative to parent with percentage offsets
|
||||||
|
luaunit.assertEquals(child.positioning, Positioning.RELATIVE)
|
||||||
|
luaunit.assertEquals(child.x, 70.0) -- parent.x (50) + 10% of width (20)
|
||||||
|
luaunit.assertEquals(child.y, 120.0) -- parent.y (100) + 20% of height (20)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Test 3: Relative positioning with no offset (default to parent position)
|
||||||
|
function TestRelativePositioning.testRelativePositioningNoOffset()
|
||||||
|
local parent = Gui.new({
|
||||||
|
x = 75,
|
||||||
|
y = 125,
|
||||||
|
w = 150,
|
||||||
|
h = 200,
|
||||||
|
positioning = "relative",
|
||||||
|
background = Color.new(0.2, 0.2, 0.2, 1.0),
|
||||||
|
})
|
||||||
|
|
||||||
|
local child = Gui.new({
|
||||||
|
parent = parent,
|
||||||
|
w = 40,
|
||||||
|
h = 30,
|
||||||
|
positioning = "relative",
|
||||||
|
background = Color.new(0.2, 0.8, 0.2, 1.0)
|
||||||
|
})
|
||||||
|
|
||||||
|
-- Child should be positioned at parent's position with no offset
|
||||||
|
luaunit.assertEquals(child.positioning, Positioning.RELATIVE)
|
||||||
|
luaunit.assertEquals(child.x, 75) -- same as parent.x
|
||||||
|
luaunit.assertEquals(child.y, 125) -- same as parent.y
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Test 4: Multiple relative positioned children
|
||||||
|
function TestRelativePositioning.testMultipleRelativeChildren()
|
||||||
|
local parent = Gui.new({
|
||||||
|
x = 200,
|
||||||
|
y = 300,
|
||||||
|
w = 100,
|
||||||
|
h = 100,
|
||||||
|
positioning = "relative",
|
||||||
|
background = Color.new(0.2, 0.2, 0.2, 1.0),
|
||||||
|
})
|
||||||
|
|
||||||
|
local child1 = Gui.new({
|
||||||
|
parent = parent,
|
||||||
|
x = 10,
|
||||||
|
y = 15,
|
||||||
|
w = 20,
|
||||||
|
h = 20,
|
||||||
|
positioning = "relative",
|
||||||
|
background = Color.new(0.8, 0.2, 0.2, 1.0)
|
||||||
|
})
|
||||||
|
|
||||||
|
local child2 = Gui.new({
|
||||||
|
parent = parent,
|
||||||
|
x = 30,
|
||||||
|
y = 45,
|
||||||
|
w = 25,
|
||||||
|
h = 25,
|
||||||
|
positioning = "relative",
|
||||||
|
background = Color.new(0.2, 0.8, 0.2, 1.0)
|
||||||
|
})
|
||||||
|
|
||||||
|
-- Both children should be positioned relative to parent
|
||||||
|
luaunit.assertEquals(child1.x, 210) -- parent.x (200) + offset (10)
|
||||||
|
luaunit.assertEquals(child1.y, 315) -- parent.y (300) + offset (15)
|
||||||
|
|
||||||
|
luaunit.assertEquals(child2.x, 230) -- parent.x (200) + offset (30)
|
||||||
|
luaunit.assertEquals(child2.y, 345) -- parent.y (300) + offset (45)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Test 5: Nested relative positioning
|
||||||
|
function TestRelativePositioning.testNestedRelativePositioning()
|
||||||
|
local grandparent = Gui.new({
|
||||||
|
x = 50,
|
||||||
|
y = 60,
|
||||||
|
w = 300,
|
||||||
|
h = 250,
|
||||||
|
positioning = "relative",
|
||||||
|
background = Color.new(0.1, 0.1, 0.1, 1.0),
|
||||||
|
})
|
||||||
|
|
||||||
|
local parent = Gui.new({
|
||||||
|
parent = grandparent,
|
||||||
|
x = 25,
|
||||||
|
y = 35,
|
||||||
|
w = 200,
|
||||||
|
h = 150,
|
||||||
|
positioning = "relative",
|
||||||
|
background = Color.new(0.3, 0.3, 0.3, 1.0),
|
||||||
|
})
|
||||||
|
|
||||||
|
local child = Gui.new({
|
||||||
|
parent = parent,
|
||||||
|
x = 15,
|
||||||
|
y = 20,
|
||||||
|
w = 50,
|
||||||
|
h = 40,
|
||||||
|
positioning = "relative",
|
||||||
|
background = Color.new(0.8, 0.8, 0.8, 1.0)
|
||||||
|
})
|
||||||
|
|
||||||
|
-- Each level should be positioned relative to its parent
|
||||||
|
luaunit.assertEquals(parent.x, 75) -- grandparent.x (50) + offset (25)
|
||||||
|
luaunit.assertEquals(parent.y, 95) -- grandparent.y (60) + offset (35)
|
||||||
|
|
||||||
|
luaunit.assertEquals(child.x, 90) -- parent.x (75) + offset (15)
|
||||||
|
luaunit.assertEquals(child.y, 115) -- parent.y (95) + offset (20)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Test 6: Mixed positioning types (relative child in absolute parent)
|
||||||
|
function TestRelativePositioning.testMixedPositioning()
|
||||||
|
local parent = Gui.new({
|
||||||
|
x = 100,
|
||||||
|
y = 200,
|
||||||
|
w = 180,
|
||||||
|
h = 120,
|
||||||
|
positioning = "absolute",
|
||||||
|
background = Color.new(0.2, 0.2, 0.2, 1.0),
|
||||||
|
})
|
||||||
|
|
||||||
|
local child = Gui.new({
|
||||||
|
parent = parent,
|
||||||
|
x = 40,
|
||||||
|
y = 25,
|
||||||
|
w = 60,
|
||||||
|
h = 35,
|
||||||
|
positioning = "relative",
|
||||||
|
background = Color.new(0.8, 0.8, 0.2, 1.0)
|
||||||
|
})
|
||||||
|
|
||||||
|
-- Relative child should still be positioned relative to absolute parent
|
||||||
|
luaunit.assertEquals(parent.positioning, Positioning.ABSOLUTE)
|
||||||
|
luaunit.assertEquals(child.positioning, Positioning.RELATIVE)
|
||||||
|
luaunit.assertEquals(child.x, 140) -- parent.x (100) + offset (40)
|
||||||
|
luaunit.assertEquals(child.y, 225) -- parent.y (200) + offset (25)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Run all tests
|
||||||
|
os.exit(luaunit.LuaUnit.run())
|
||||||
124
testing/__tests__/14_text_scaling_basic_tests.lua
Normal file
124
testing/__tests__/14_text_scaling_basic_tests.lua
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
-- Test file for basic text scaling functionality
|
||||||
|
-- This tests simple cases where elements scale text appropriately during resize
|
||||||
|
|
||||||
|
package.path = './testing/?.lua;./?.lua;' .. package.path
|
||||||
|
local luaunit = require("luaunit")
|
||||||
|
|
||||||
|
-- Mock love module for testing
|
||||||
|
love = {
|
||||||
|
graphics = {
|
||||||
|
getDimensions = function() return 800, 600 end,
|
||||||
|
newFont = function(size) return { getWidth = function(text) return size * #text end, getHeight = function() return size end } end,
|
||||||
|
getFont = function() return { getWidth = function(text) return 12 * #text end, getHeight = function() return 12 end } end,
|
||||||
|
},
|
||||||
|
window = {
|
||||||
|
getMode = function() return 800, 600 end
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Import the FlexLove library
|
||||||
|
local FlexLove = require("FlexLove")
|
||||||
|
local Gui = FlexLove.GUI
|
||||||
|
|
||||||
|
-- Test suite for basic text scaling
|
||||||
|
local BasicTextScalingTests = {}
|
||||||
|
|
||||||
|
function BasicTextScalingTests.testFixedTextSize()
|
||||||
|
-- Create an element with fixed textSize in pixels
|
||||||
|
local element = Gui.new({
|
||||||
|
id = "testElement",
|
||||||
|
w = 100,
|
||||||
|
h = 50,
|
||||||
|
textSize = 16, -- Fixed size in pixels
|
||||||
|
text = "Hello World"
|
||||||
|
})
|
||||||
|
|
||||||
|
-- Check initial state
|
||||||
|
luaunit.assertEquals(element.textSize, 16)
|
||||||
|
|
||||||
|
-- Simulate a resize with larger viewport
|
||||||
|
local newWidth, newHeight = 800, 600
|
||||||
|
element:resize(newWidth, newHeight)
|
||||||
|
|
||||||
|
-- Fixed textSize should remain unchanged
|
||||||
|
luaunit.assertEquals(element.textSize, 16)
|
||||||
|
end
|
||||||
|
|
||||||
|
function BasicTextScalingTests.testPercentageTextSize()
|
||||||
|
-- Create an element with percentage textSize
|
||||||
|
local element = Gui.new({
|
||||||
|
id = "testElement",
|
||||||
|
w = 100,
|
||||||
|
h = 50,
|
||||||
|
textSize = "5%", -- Percentage of viewport height
|
||||||
|
text = "Hello World"
|
||||||
|
})
|
||||||
|
|
||||||
|
-- Check initial state
|
||||||
|
luaunit.assertEquals(element.units.textSize.unit, "%")
|
||||||
|
|
||||||
|
-- Simulate a resize with larger viewport
|
||||||
|
local newWidth, newHeight = 800, 600
|
||||||
|
element:resize(newWidth, newHeight)
|
||||||
|
|
||||||
|
-- Percentage textSize should be recalculated
|
||||||
|
luaunit.assertEquals(element.textSize, 30) -- 5% of 600 height = 30
|
||||||
|
end
|
||||||
|
|
||||||
|
function BasicTextScalingTests.testVwTextSize()
|
||||||
|
-- Create an element with vw textSize
|
||||||
|
local element = Gui.new({
|
||||||
|
id = "testElement",
|
||||||
|
w = 100,
|
||||||
|
h = 50,
|
||||||
|
textSize = "2vw", -- 2% of viewport width
|
||||||
|
text = "Hello World"
|
||||||
|
})
|
||||||
|
|
||||||
|
-- Check initial state
|
||||||
|
luaunit.assertEquals(element.units.textSize.unit, "vw")
|
||||||
|
|
||||||
|
-- Simulate a resize with larger viewport
|
||||||
|
local newWidth, newHeight = 800, 600
|
||||||
|
element:resize(newWidth, newHeight)
|
||||||
|
|
||||||
|
-- vw textSize should be recalculated
|
||||||
|
luaunit.assertEquals(element.textSize, 16) -- 2% of 800 width = 16
|
||||||
|
end
|
||||||
|
|
||||||
|
function BasicTextScalingTests.testVhTextSize()
|
||||||
|
-- Create an element with vh textSize
|
||||||
|
local element = Gui.new({
|
||||||
|
id = "testElement",
|
||||||
|
w = 100,
|
||||||
|
h = 50,
|
||||||
|
textSize = "3vh", -- 3% of viewport height
|
||||||
|
text = "Hello World"
|
||||||
|
})
|
||||||
|
|
||||||
|
-- Check initial state
|
||||||
|
luaunit.assertEquals(element.units.textSize.unit, "vh")
|
||||||
|
|
||||||
|
-- Simulate a resize with larger viewport
|
||||||
|
local newWidth, newHeight = 800, 600
|
||||||
|
element:resize(newWidth, newHeight)
|
||||||
|
|
||||||
|
-- vh textSize should be recalculated
|
||||||
|
luaunit.assertEquals(element.textSize, 18) -- 3% of 600 height = 18
|
||||||
|
end
|
||||||
|
|
||||||
|
function BasicTextScalingTests.testNoTextSize()
|
||||||
|
-- Create an element without textSize specified
|
||||||
|
local element = Gui.new({
|
||||||
|
id = "testElement",
|
||||||
|
w = 100,
|
||||||
|
h = 50,
|
||||||
|
text = "Hello World"
|
||||||
|
})
|
||||||
|
|
||||||
|
-- Check initial state - should default to some value
|
||||||
|
luaunit.assertEquals(element.units.textSize.value, nil)
|
||||||
|
luaunit.assertEquals(element.textSize, 12) -- Default fallback
|
||||||
|
end
|
||||||
|
|
||||||
|
return BasicTextScalingTests
|
||||||
Reference in New Issue
Block a user