fixes for the absolute positioning bug
This commit is contained in:
@@ -1308,6 +1308,91 @@ function Element.new(props)
|
||||
self._originalPositioning = nil -- No explicit positioning
|
||||
self._explicitlyAbsolute = false
|
||||
end
|
||||
|
||||
-- Handle positioning properties for elements without parent
|
||||
-- Handle top positioning with units
|
||||
if props.top then
|
||||
local isCalc = Element._Calc and Element._Calc.isCalc(props.top)
|
||||
if type(props.top) == "string" or isCalc then
|
||||
local value, unit = Element._Units.parse(props.top)
|
||||
self.units.top = { value = value, unit = unit }
|
||||
local resolvedTop = Element._Units.resolve(value, unit, viewportWidth, viewportHeight, viewportHeight)
|
||||
if type(resolvedTop) ~= "number" then
|
||||
Element._ErrorHandler:warn("Element", "LAY_003", {
|
||||
issue = "top resolution returned non-number value",
|
||||
type = type(resolvedTop),
|
||||
})
|
||||
resolvedTop = 0
|
||||
end
|
||||
self.top = resolvedTop
|
||||
else
|
||||
self.top = props.top
|
||||
self.units.top = { value = props.top, unit = "px" }
|
||||
end
|
||||
end
|
||||
|
||||
-- Handle right positioning with units
|
||||
if props.right then
|
||||
local isCalc = Element._Calc and Element._Calc.isCalc(props.right)
|
||||
if type(props.right) == "string" or isCalc then
|
||||
local value, unit = Element._Units.parse(props.right)
|
||||
self.units.right = { value = value, unit = unit }
|
||||
local resolvedRight = Element._Units.resolve(value, unit, viewportWidth, viewportHeight, viewportWidth)
|
||||
if type(resolvedRight) ~= "number" then
|
||||
Element._ErrorHandler:warn("Element", "LAY_003", {
|
||||
issue = "right resolution returned non-number value",
|
||||
type = type(resolvedRight),
|
||||
})
|
||||
resolvedRight = 0
|
||||
end
|
||||
self.right = resolvedRight
|
||||
else
|
||||
self.right = props.right
|
||||
self.units.right = { value = props.right, unit = "px" }
|
||||
end
|
||||
end
|
||||
|
||||
-- Handle bottom positioning with units
|
||||
if props.bottom then
|
||||
local isCalc = Element._Calc and Element._Calc.isCalc(props.bottom)
|
||||
if type(props.bottom) == "string" or isCalc then
|
||||
local value, unit = Element._Units.parse(props.bottom)
|
||||
self.units.bottom = { value = value, unit = unit }
|
||||
local resolvedBottom = Element._Units.resolve(value, unit, viewportWidth, viewportHeight, viewportHeight)
|
||||
if type(resolvedBottom) ~= "number" then
|
||||
Element._ErrorHandler:warn("Element", "LAY_003", {
|
||||
issue = "bottom resolution returned non-number value",
|
||||
type = type(resolvedBottom),
|
||||
})
|
||||
resolvedBottom = 0
|
||||
end
|
||||
self.bottom = resolvedBottom
|
||||
else
|
||||
self.bottom = props.bottom
|
||||
self.units.bottom = { value = props.bottom, unit = "px" }
|
||||
end
|
||||
end
|
||||
|
||||
-- Handle left positioning with units
|
||||
if props.left then
|
||||
local isCalc = Element._Calc and Element._Calc.isCalc(props.left)
|
||||
if type(props.left) == "string" or isCalc then
|
||||
local value, unit = Element._Units.parse(props.left)
|
||||
self.units.left = { value = value, unit = unit }
|
||||
local resolvedLeft = Element._Units.resolve(value, unit, viewportWidth, viewportHeight, viewportWidth)
|
||||
if type(resolvedLeft) ~= "number" then
|
||||
Element._ErrorHandler:warn("Element", "LAY_003", {
|
||||
issue = "left resolution returned non-number value",
|
||||
type = type(resolvedLeft),
|
||||
})
|
||||
resolvedLeft = 0
|
||||
end
|
||||
self.left = resolvedLeft
|
||||
else
|
||||
self.left = props.left
|
||||
self.units.left = { value = props.left, unit = "px" }
|
||||
end
|
||||
end
|
||||
else
|
||||
-- Set positioning first and track if explicitly set
|
||||
self._originalPositioning = props.positioning -- Track original intent
|
||||
@@ -1468,106 +1553,94 @@ function Element.new(props)
|
||||
end
|
||||
end
|
||||
|
||||
-- Handle positioning properties BEFORE adding to parent (so they're available during layout)
|
||||
-- Handle top positioning with units
|
||||
if props.top then
|
||||
local isCalc = Element._Calc and Element._Calc.isCalc(props.top)
|
||||
if type(props.top) == "string" or isCalc then
|
||||
local value, unit = Element._Units.parse(props.top)
|
||||
self.units.top = { value = value, unit = unit }
|
||||
local resolvedTop = Element._Units.resolve(value, unit, viewportWidth, viewportHeight, viewportHeight)
|
||||
if type(resolvedTop) ~= "number" then
|
||||
Element._ErrorHandler:warn("Element", "LAY_003", {
|
||||
issue = "top resolution returned non-number value",
|
||||
type = type(resolvedTop),
|
||||
})
|
||||
resolvedTop = 0
|
||||
end
|
||||
self.top = resolvedTop
|
||||
else
|
||||
self.top = props.top
|
||||
self.units.top = { value = props.top, unit = "px" }
|
||||
end
|
||||
end
|
||||
|
||||
-- Handle right positioning with units
|
||||
if props.right then
|
||||
local isCalc = Element._Calc and Element._Calc.isCalc(props.right)
|
||||
if type(props.right) == "string" or isCalc then
|
||||
local value, unit = Element._Units.parse(props.right)
|
||||
self.units.right = { value = value, unit = unit }
|
||||
local resolvedRight = Element._Units.resolve(value, unit, viewportWidth, viewportHeight, viewportWidth)
|
||||
if type(resolvedRight) ~= "number" then
|
||||
Element._ErrorHandler:warn("Element", "LAY_003", {
|
||||
issue = "right resolution returned non-number value",
|
||||
type = type(resolvedRight),
|
||||
})
|
||||
resolvedRight = 0
|
||||
end
|
||||
self.right = resolvedRight
|
||||
else
|
||||
self.right = props.right
|
||||
self.units.right = { value = props.right, unit = "px" }
|
||||
end
|
||||
end
|
||||
|
||||
-- Handle bottom positioning with units
|
||||
if props.bottom then
|
||||
local isCalc = Element._Calc and Element._Calc.isCalc(props.bottom)
|
||||
if type(props.bottom) == "string" or isCalc then
|
||||
local value, unit = Element._Units.parse(props.bottom)
|
||||
self.units.bottom = { value = value, unit = unit }
|
||||
local resolvedBottom = Element._Units.resolve(value, unit, viewportWidth, viewportHeight, viewportHeight)
|
||||
if type(resolvedBottom) ~= "number" then
|
||||
Element._ErrorHandler:warn("Element", "LAY_003", {
|
||||
issue = "bottom resolution returned non-number value",
|
||||
type = type(resolvedBottom),
|
||||
})
|
||||
resolvedBottom = 0
|
||||
end
|
||||
self.bottom = resolvedBottom
|
||||
else
|
||||
self.bottom = props.bottom
|
||||
self.units.bottom = { value = props.bottom, unit = "px" }
|
||||
end
|
||||
end
|
||||
|
||||
-- Handle left positioning with units
|
||||
if props.left then
|
||||
local isCalc = Element._Calc and Element._Calc.isCalc(props.left)
|
||||
if type(props.left) == "string" or isCalc then
|
||||
local value, unit = Element._Units.parse(props.left)
|
||||
self.units.left = { value = value, unit = unit }
|
||||
local resolvedLeft = Element._Units.resolve(value, unit, viewportWidth, viewportHeight, viewportWidth)
|
||||
if type(resolvedLeft) ~= "number" then
|
||||
Element._ErrorHandler:warn("Element", "LAY_003", {
|
||||
issue = "left resolution returned non-number value",
|
||||
type = type(resolvedLeft),
|
||||
})
|
||||
resolvedLeft = 0
|
||||
end
|
||||
self.left = resolvedLeft
|
||||
else
|
||||
self.left = props.left
|
||||
self.units.left = { value = props.left, unit = "px" }
|
||||
end
|
||||
end
|
||||
|
||||
props.parent:addChild(self)
|
||||
end
|
||||
|
||||
-- Handle positioning properties for ALL elements (with or without parent)
|
||||
-- Handle top positioning with units
|
||||
if props.top then
|
||||
local isCalc = Element._Calc and Element._Calc.isCalc(props.top)
|
||||
if type(props.top) == "string" or isCalc then
|
||||
local value, unit = Element._Units.parse(props.top)
|
||||
self.units.top = { value = value, unit = unit }
|
||||
local resolvedTop = Element._Units.resolve(value, unit, viewportWidth, viewportHeight, viewportHeight)
|
||||
if type(resolvedTop) ~= "number" then
|
||||
Element._ErrorHandler:warn("Element", "LAY_003", {
|
||||
issue = "top resolution returned non-number value",
|
||||
type = type(resolvedTop),
|
||||
})
|
||||
resolvedTop = 0
|
||||
end
|
||||
self.top = resolvedTop
|
||||
else
|
||||
self.top = props.top
|
||||
self.units.top = { value = props.top, unit = "px" }
|
||||
end
|
||||
else
|
||||
self.top = nil
|
||||
self.units.top = nil
|
||||
end
|
||||
|
||||
-- Handle right positioning with units
|
||||
if props.right then
|
||||
local isCalc = Element._Calc and Element._Calc.isCalc(props.right)
|
||||
if type(props.right) == "string" or isCalc then
|
||||
local value, unit = Element._Units.parse(props.right)
|
||||
self.units.right = { value = value, unit = unit }
|
||||
local resolvedRight = Element._Units.resolve(value, unit, viewportWidth, viewportHeight, viewportWidth)
|
||||
if type(resolvedRight) ~= "number" then
|
||||
Element._ErrorHandler:warn("Element", "LAY_003", {
|
||||
issue = "right resolution returned non-number value",
|
||||
type = type(resolvedRight),
|
||||
})
|
||||
resolvedRight = 0
|
||||
end
|
||||
self.right = resolvedRight
|
||||
else
|
||||
self.right = props.right
|
||||
self.units.right = { value = props.right, unit = "px" }
|
||||
end
|
||||
else
|
||||
self.right = nil
|
||||
self.units.right = nil
|
||||
end
|
||||
|
||||
-- Handle bottom positioning with units
|
||||
if props.bottom then
|
||||
local isCalc = Element._Calc and Element._Calc.isCalc(props.bottom)
|
||||
if type(props.bottom) == "string" or isCalc then
|
||||
local value, unit = Element._Units.parse(props.bottom)
|
||||
self.units.bottom = { value = value, unit = unit }
|
||||
local resolvedBottom = Element._Units.resolve(value, unit, viewportWidth, viewportHeight, viewportHeight)
|
||||
if type(resolvedBottom) ~= "number" then
|
||||
Element._ErrorHandler:warn("Element", "LAY_003", {
|
||||
issue = "bottom resolution returned non-number value",
|
||||
type = type(resolvedBottom),
|
||||
})
|
||||
resolvedBottom = 0
|
||||
end
|
||||
self.bottom = resolvedBottom
|
||||
else
|
||||
self.bottom = props.bottom
|
||||
self.units.bottom = { value = props.bottom, unit = "px" }
|
||||
end
|
||||
else
|
||||
self.bottom = nil
|
||||
self.units.bottom = nil
|
||||
end
|
||||
|
||||
-- Handle left positioning with units
|
||||
if props.left then
|
||||
local isCalc = Element._Calc and Element._Calc.isCalc(props.left)
|
||||
if type(props.left) == "string" or isCalc then
|
||||
local value, unit = Element._Units.parse(props.left)
|
||||
self.units.left = { value = value, unit = unit }
|
||||
local resolvedLeft = Element._Units.resolve(value, unit, viewportWidth, viewportHeight, viewportWidth)
|
||||
if type(resolvedLeft) ~= "number" then
|
||||
Element._ErrorHandler:warn("Element", "LAY_003", {
|
||||
issue = "left resolution returned non-number value",
|
||||
type = type(resolvedLeft),
|
||||
})
|
||||
resolvedLeft = 0
|
||||
end
|
||||
self.left = resolvedLeft
|
||||
else
|
||||
self.left = props.left
|
||||
self.units.left = { value = props.left, unit = "px" }
|
||||
end
|
||||
else
|
||||
self.left = nil
|
||||
self.units.left = nil
|
||||
end
|
||||
|
||||
if self.positioning == Element._utils.enums.Positioning.FLEX then
|
||||
-- Validate enum properties
|
||||
if props.flexDirection then
|
||||
@@ -2135,6 +2208,9 @@ function Element:addChild(child)
|
||||
|
||||
table.insert(self.children, child)
|
||||
|
||||
-- Mark parent as having dirty children to trigger layout recalculation
|
||||
self._childrenDirty = true
|
||||
|
||||
-- Only recalculate auto-sizing if the child participates in layout
|
||||
-- (CSS: absolutely positioned children don't affect parent auto-sizing)
|
||||
if not child._explicitlyAbsolute then
|
||||
|
||||
@@ -123,6 +123,8 @@ end
|
||||
--- Apply CSS positioning offsets (top, right, bottom, left) to a child element
|
||||
---@param child Element The element to apply offsets to
|
||||
function LayoutEngine:applyPositioningOffsets(child)
|
||||
|
||||
|
||||
if not child then
|
||||
return
|
||||
end
|
||||
@@ -139,7 +141,7 @@ function LayoutEngine:applyPositioningOffsets(child)
|
||||
or child.positioning == self._Positioning.GRID
|
||||
or (child.positioning == self._Positioning.ABSOLUTE and not child._explicitlyAbsolute)
|
||||
|
||||
if not isFlexChild then
|
||||
if not isFlexChild and child._explicitlyAbsolute then
|
||||
-- Apply absolute positioning for explicitly absolute children
|
||||
-- Apply top offset (distance from parent's content box top edge)
|
||||
if child.top then
|
||||
@@ -224,6 +226,7 @@ end
|
||||
|
||||
--- Layout children within this element according to positioning mode
|
||||
function LayoutEngine:layoutChildren()
|
||||
|
||||
-- Start performance timing first (before any early returns)
|
||||
local timerName = nil
|
||||
if LayoutEngine._Performance and LayoutEngine._Performance.enabled and self.element then
|
||||
@@ -250,9 +253,23 @@ function LayoutEngine:layoutChildren()
|
||||
if self.positioning == self._Positioning.ABSOLUTE or self.positioning == self._Positioning.RELATIVE then
|
||||
-- Absolute/Relative positioned containers don't layout their children according to flex rules,
|
||||
-- but they should still apply CSS positioning offsets to their children
|
||||
local baseX = (self.element.x or 0) + self.element.padding.left
|
||||
local baseY = (self.element.y or 0) + self.element.padding.top
|
||||
|
||||
for _, child in ipairs(self.element.children) do
|
||||
-- Apply CSS positioning offsets to children with absolute positioning
|
||||
if child.top or child.right or child.bottom or child.left then
|
||||
self:applyPositioningOffsets(child)
|
||||
elseif child.positioning == self._Positioning.RELATIVE then
|
||||
-- Reposition relative children to match parent's new position
|
||||
-- This is needed when the parent (absolute container) moves after children are created
|
||||
child.x = baseX
|
||||
child.y = baseY
|
||||
|
||||
-- If child has children, recursively layout them
|
||||
if #child.children > 0 then
|
||||
child:layoutChildren()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -316,81 +333,45 @@ function LayoutEngine:layoutChildren()
|
||||
end
|
||||
end
|
||||
|
||||
-- CSS-compliant behavior: absolutely positioned elements are completely removed from normal flow
|
||||
-- They do NOT reserve space or affect flex layout calculations at all
|
||||
|
||||
-- If no flex children, skip flex layout but still position absolute children
|
||||
if #flexChildren == 0 then
|
||||
return
|
||||
end
|
||||
|
||||
-- Calculate space reserved by absolutely positioned siblings with explicit positioning
|
||||
local reservedMainStart = 0 -- Space reserved at the start of main axis (left for horizontal, top for vertical)
|
||||
local reservedMainEnd = 0 -- Space reserved at the end of main axis (right for horizontal, bottom for vertical)
|
||||
local reservedCrossStart = 0 -- Space reserved at the start of cross axis (top for horizontal, left for vertical)
|
||||
local reservedCrossEnd = 0 -- Space reserved at the end of cross axis (bottom for horizontal, right for vertical)
|
||||
|
||||
for _, child in ipairs(self.element.children) do
|
||||
-- Only consider absolutely positioned children with explicit positioning
|
||||
if child.positioning == self._Positioning.ABSOLUTE and child._explicitlyAbsolute then
|
||||
-- BORDER-BOX MODEL: Use border-box dimensions for space calculations
|
||||
local childBorderBoxWidth = child:getBorderBoxWidth()
|
||||
local childBorderBoxHeight = child:getBorderBoxHeight()
|
||||
|
||||
if self.flexDirection == self._FlexDirection.HORIZONTAL then
|
||||
-- Horizontal layout: main axis is X, cross axis is Y
|
||||
-- Check for left positioning (reserves space at main axis start)
|
||||
if child.left then
|
||||
local spaceNeeded = child.left + childBorderBoxWidth
|
||||
reservedMainStart = math.max(reservedMainStart, spaceNeeded)
|
||||
end
|
||||
-- Check for right positioning (reserves space at main axis end)
|
||||
if child.right then
|
||||
local spaceNeeded = child.right + childBorderBoxWidth
|
||||
reservedMainEnd = math.max(reservedMainEnd, spaceNeeded)
|
||||
end
|
||||
-- Check for top positioning (reserves space at cross axis start)
|
||||
if child.top then
|
||||
local spaceNeeded = child.top + childBorderBoxHeight
|
||||
reservedCrossStart = math.max(reservedCrossStart, spaceNeeded)
|
||||
end
|
||||
-- Check for bottom positioning (reserves space at cross axis end)
|
||||
if child.bottom then
|
||||
local spaceNeeded = child.bottom + childBorderBoxHeight
|
||||
reservedCrossEnd = math.max(reservedCrossEnd, spaceNeeded)
|
||||
end
|
||||
else
|
||||
-- Vertical layout: main axis is Y, cross axis is X
|
||||
-- Check for top positioning (reserves space at main axis start)
|
||||
if child.top then
|
||||
local spaceNeeded = child.top + childBorderBoxHeight
|
||||
reservedMainStart = math.max(reservedMainStart, spaceNeeded)
|
||||
end
|
||||
-- Check for bottom positioning (reserves space at main axis end)
|
||||
if child.bottom then
|
||||
local spaceNeeded = child.bottom + childBorderBoxHeight
|
||||
reservedMainEnd = math.max(reservedMainEnd, spaceNeeded)
|
||||
end
|
||||
-- Check for left positioning (reserves space at cross axis start)
|
||||
if child.left then
|
||||
local spaceNeeded = child.left + childBorderBoxWidth
|
||||
reservedCrossStart = math.max(reservedCrossStart, spaceNeeded)
|
||||
end
|
||||
-- Check for right positioning (reserves space at cross axis end)
|
||||
if child.right then
|
||||
local spaceNeeded = child.right + childBorderBoxWidth
|
||||
reservedCrossEnd = math.max(reservedCrossEnd, spaceNeeded)
|
||||
-- Position absolutely positioned children even when there are no flex children
|
||||
for i, child in ipairs(self.element.children) do
|
||||
if child.positioning == self._Positioning.ABSOLUTE and child._explicitlyAbsolute then
|
||||
self:applyPositioningOffsets(child)
|
||||
|
||||
-- If child has children, layout them after position change
|
||||
if #child.children > 0 then
|
||||
child:layoutChildren()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Detect overflow after children positioning
|
||||
if self.element._detectOverflow then
|
||||
self.element:_detectOverflow()
|
||||
end
|
||||
|
||||
-- Stop performance timing
|
||||
if timerName and LayoutEngine._Performance then
|
||||
LayoutEngine._Performance:stopTimer(timerName)
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
-- Calculate available space (accounting for padding and reserved space)
|
||||
|
||||
-- Calculate available space (accounting for padding only, NOT absolute children)
|
||||
-- BORDER-BOX MODEL: element.width and element.height are already content dimensions (padding subtracted)
|
||||
local availableMainSize = 0
|
||||
local availableCrossSize = 0
|
||||
if self.flexDirection == self._FlexDirection.HORIZONTAL then
|
||||
availableMainSize = self.element.width - reservedMainStart - reservedMainEnd
|
||||
availableCrossSize = self.element.height - reservedCrossStart - reservedCrossEnd
|
||||
availableMainSize = self.element.width
|
||||
availableCrossSize = self.element.height
|
||||
else
|
||||
availableMainSize = self.element.height - reservedMainStart - reservedMainEnd
|
||||
availableCrossSize = self.element.width - reservedCrossStart - reservedCrossEnd
|
||||
availableMainSize = self.element.height
|
||||
availableCrossSize = self.element.width
|
||||
end
|
||||
|
||||
-- Handle flex wrap: create lines of children
|
||||
@@ -614,9 +595,9 @@ function LayoutEngine:layoutChildren()
|
||||
if self.flexDirection == self._FlexDirection.HORIZONTAL then
|
||||
-- Horizontal layout: main axis is X, cross axis is Y
|
||||
-- Position child at border box (x, y represents top-left including padding)
|
||||
-- Add reservedMainStart and left margin to account for absolutely positioned siblings and margins
|
||||
-- CSS-compliant: absolute children don't affect flex positioning, so no reserved space offset
|
||||
local childMarginLeft = childMargin.left
|
||||
child.x = elementX + elementPaddingLeft + reservedMainStart + currentMainPos + childMarginLeft
|
||||
child.x = elementX + elementPaddingLeft + currentMainPos + childMarginLeft
|
||||
|
||||
-- BORDER-BOX MODEL: Use border-box dimensions for alignment calculations
|
||||
local childBorderBoxHeight = child:getBorderBoxHeight()
|
||||
@@ -625,16 +606,15 @@ function LayoutEngine:layoutChildren()
|
||||
local childTotalCrossSize = childBorderBoxHeight + childMarginTop + childMarginBottom
|
||||
|
||||
if effectiveAlign == alignItems_FLEX_START then
|
||||
child.y = elementY + elementPaddingTop + reservedCrossStart + currentCrossPos + childMarginTop
|
||||
child.y = elementY + elementPaddingTop + currentCrossPos + childMarginTop
|
||||
elseif effectiveAlign == alignItems_CENTER then
|
||||
child.y = elementY
|
||||
+ elementPaddingTop
|
||||
+ reservedCrossStart
|
||||
+ currentCrossPos
|
||||
+ ((lineHeight - childTotalCrossSize) / 2)
|
||||
+ childMarginTop
|
||||
elseif effectiveAlign == alignItems_FLEX_END then
|
||||
child.y = elementY + elementPaddingTop + reservedCrossStart + currentCrossPos + lineHeight - childTotalCrossSize + childMarginTop
|
||||
child.y = elementY + elementPaddingTop + currentCrossPos + lineHeight - childTotalCrossSize + childMarginTop
|
||||
elseif effectiveAlign == alignItems_STRETCH then
|
||||
-- STRETCH: Only apply if height was not explicitly set
|
||||
if childAutosizing and childAutosizing.height then
|
||||
@@ -643,7 +623,7 @@ function LayoutEngine:layoutChildren()
|
||||
child._borderBoxHeight = availableHeight
|
||||
child.height = math.max(0, availableHeight - childPadding.top - childPadding.bottom)
|
||||
end
|
||||
child.y = elementY + elementPaddingTop + reservedCrossStart + currentCrossPos + childMarginTop
|
||||
child.y = elementY + elementPaddingTop + currentCrossPos + childMarginTop
|
||||
end
|
||||
|
||||
-- Apply positioning offsets (top, right, bottom, left)
|
||||
@@ -659,9 +639,9 @@ function LayoutEngine:layoutChildren()
|
||||
else
|
||||
-- Vertical layout: main axis is Y, cross axis is X
|
||||
-- Position child at border box (x, y represents top-left including padding)
|
||||
-- Add reservedMainStart and top margin to account for absolutely positioned siblings and margins
|
||||
-- CSS-compliant: absolute children don't affect flex positioning, so no reserved space offset
|
||||
local childMarginTop = childMargin.top
|
||||
child.y = elementY + elementPaddingTop + reservedMainStart + currentMainPos + childMarginTop
|
||||
child.y = elementY + elementPaddingTop + currentMainPos + childMarginTop
|
||||
|
||||
-- BORDER-BOX MODEL: Use border-box dimensions for alignment calculations
|
||||
local childBorderBoxWidth = child:getBorderBoxWidth()
|
||||
@@ -671,16 +651,15 @@ function LayoutEngine:layoutChildren()
|
||||
local elementPaddingLeft = elementPadding.left
|
||||
|
||||
if effectiveAlign == alignItems_FLEX_START then
|
||||
child.x = elementX + elementPaddingLeft + reservedCrossStart + currentCrossPos + childMarginLeft
|
||||
child.x = elementX + elementPaddingLeft + currentCrossPos + childMarginLeft
|
||||
elseif effectiveAlign == alignItems_CENTER then
|
||||
child.x = elementX
|
||||
+ elementPaddingLeft
|
||||
+ reservedCrossStart
|
||||
+ currentCrossPos
|
||||
+ ((lineHeight - childTotalCrossSize) / 2)
|
||||
+ childMarginLeft
|
||||
elseif effectiveAlign == alignItems_FLEX_END then
|
||||
child.x = elementX + elementPaddingLeft + reservedCrossStart + currentCrossPos + lineHeight - childTotalCrossSize + childMarginLeft
|
||||
child.x = elementX + elementPaddingLeft + currentCrossPos + lineHeight - childTotalCrossSize + childMarginLeft
|
||||
elseif effectiveAlign == alignItems_STRETCH then
|
||||
-- STRETCH: Only apply if width was not explicitly set
|
||||
if childAutosizing and childAutosizing.width then
|
||||
@@ -689,7 +668,7 @@ function LayoutEngine:layoutChildren()
|
||||
child._borderBoxWidth = availableWidth
|
||||
child.width = math.max(0, availableWidth - childPadding.left - childPadding.right)
|
||||
end
|
||||
child.x = elementX + elementPaddingLeft + reservedCrossStart + currentCrossPos + childMarginLeft
|
||||
child.x = elementX + elementPaddingLeft + currentCrossPos + childMarginLeft
|
||||
end
|
||||
|
||||
-- Apply positioning offsets (top, right, bottom, left)
|
||||
@@ -710,7 +689,7 @@ function LayoutEngine:layoutChildren()
|
||||
end
|
||||
|
||||
-- Position explicitly absolute children after flex layout
|
||||
for _, child in ipairs(self.element.children) do
|
||||
for i, child in ipairs(self.element.children) do
|
||||
if child.positioning == self._Positioning.ABSOLUTE and child._explicitlyAbsolute then
|
||||
-- Apply positioning offsets (top, right, bottom, left)
|
||||
self:applyPositioningOffsets(child)
|
||||
|
||||
Reference in New Issue
Block a user