fix sizing bug

This commit is contained in:
Michael Freno
2025-11-11 10:03:05 -05:00
parent 6d8324f61b
commit c19befa29e

View File

@@ -629,11 +629,20 @@ function Element.new(props)
self.width = tempWidth self.width = tempWidth
else else
self.autosizing.width = true self.autosizing.width = true
-- Special case: if textWrap is enabled and parent exists, constrain width to parent
-- Text wrapping requires a width constraint, so use parent's content width
if props.textWrap and self.parent and self.parent.width then
tempWidth = self.parent.width
self.width = tempWidth
self.units.width = { value = 100, unit = "%" } -- Mark as parent-constrained
self.autosizing.width = false -- Not truly autosizing, constrained by parent
else
-- Calculate auto-width without padding first -- Calculate auto-width without padding first
tempWidth = self:calculateAutoWidth() tempWidth = self:calculateAutoWidth()
self.width = tempWidth self.width = tempWidth
self.units.width = { value = nil, unit = "auto" } -- Mark as auto-sized self.units.width = { value = nil, unit = "auto" } -- Mark as auto-sized
end end
end
-- Handle height (both h and height properties, prefer h if both exist) -- Handle height (both h and height properties, prefer h if both exist)
local heightProp = props.height local heightProp = props.height
@@ -1970,17 +1979,43 @@ function Element:addChild(child)
-- Only recalculate auto-sizing if the child participates in layout -- Only recalculate auto-sizing if the child participates in layout
-- (CSS: absolutely positioned children don't affect parent auto-sizing) -- (CSS: absolutely positioned children don't affect parent auto-sizing)
if not child._explicitlyAbsolute then if not child._explicitlyAbsolute then
local sizeChanged = false
if self.autosizing.height then if self.autosizing.height then
local oldHeight = self.height
local contentHeight = self:calculateAutoHeight() local contentHeight = self:calculateAutoHeight()
-- BORDER-BOX MODEL: Add padding to get border-box, then subtract to get content -- BORDER-BOX MODEL: Add padding to get border-box, then subtract to get content
self._borderBoxHeight = contentHeight + self.padding.top + self.padding.bottom self._borderBoxHeight = contentHeight + self.padding.top + self.padding.bottom
self.height = contentHeight self.height = contentHeight
if oldHeight ~= self.height then
sizeChanged = true
end
end end
if self.autosizing.width then if self.autosizing.width then
local oldWidth = self.width
local contentWidth = self:calculateAutoWidth() local contentWidth = self:calculateAutoWidth()
-- BORDER-BOX MODEL: Add padding to get border-box, then subtract to get content -- BORDER-BOX MODEL: Add padding to get border-box, then subtract to get content
self._borderBoxWidth = contentWidth + self.padding.left + self.padding.right self._borderBoxWidth = contentWidth + self.padding.left + self.padding.right
self.width = contentWidth self.width = contentWidth
if oldWidth ~= self.width then
sizeChanged = true
end
end
-- Propagate size change up the tree
if sizeChanged and self.parent and (self.parent.autosizing.width or self.parent.autosizing.height) then
-- Trigger parent to recalculate its size by re-adding this child's contribution
-- This ensures grandparents are notified of size changes
if self.parent.autosizing.height then
local contentHeight = self.parent:calculateAutoHeight()
self.parent._borderBoxHeight = contentHeight + self.parent.padding.top + self.parent.padding.bottom
self.parent.height = contentHeight
end
if self.parent.autosizing.width then
local contentWidth = self.parent:calculateAutoWidth()
self.parent._borderBoxWidth = contentWidth + self.parent.padding.left + self.parent.padding.right
self.parent.width = contentWidth
end
end end
end end
@@ -3854,6 +3889,13 @@ function Element:calculateTextHeight()
if self.textWrap and (self.textWrap == "word" or self.textWrap == "char" or self.textWrap == true) then if self.textWrap and (self.textWrap == "word" or self.textWrap == "char" or self.textWrap == true) then
-- Calculate available width for wrapping -- Calculate available width for wrapping
local availableWidth = self.width local availableWidth = self.width
-- If width is not set or is 0, try to use parent's content width
if (not availableWidth or availableWidth <= 0) and self.parent then
-- Use parent's content width (excluding padding)
availableWidth = self.parent.width
end
if availableWidth and availableWidth > 0 then if availableWidth and availableWidth > 0 then
-- Get the wrapped text lines using getWrap (returns width and table of lines) -- Get the wrapped text lines using getWrap (returns width and table of lines)
local wrappedWidth, wrappedLines = font:getWrap(self.text, availableWidth) local wrappedWidth, wrappedLines = font:getWrap(self.text, availableWidth)
@@ -4674,7 +4716,7 @@ function Element:_wrapLine(line, maxWidth)
type = "space", type = "space",
text = line:sub(utf8.offset(line, wsStart), utf8.offset(line, pos) and utf8.offset(line, pos) - 1 or #line), text = line:sub(utf8.offset(line, wsStart), utf8.offset(line, pos) and utf8.offset(line, pos) - 1 or #line),
startPos = wsStart - 1, startPos = wsStart - 1,
length = pos - wsStart length = pos - wsStart,
}) })
else else
-- Collect word (non-whitespace sequence) -- Collect word (non-whitespace sequence)
@@ -4686,7 +4728,7 @@ function Element:_wrapLine(line, maxWidth)
type = "word", type = "word",
text = line:sub(utf8.offset(line, wordStart), utf8.offset(line, pos) and utf8.offset(line, pos) - 1 or #line), text = line:sub(utf8.offset(line, wordStart), utf8.offset(line, pos) and utf8.offset(line, pos) - 1 or #line),
startPos = wordStart - 1, startPos = wordStart - 1,
length = pos - wordStart length = pos - wordStart,
}) })
end end
end end
@@ -4987,7 +5029,7 @@ function Element:_getSelectionRects(selStart, selEnd)
local selY = 0 local selY = 0
local selHeight = font:getHeight() local selHeight = font:getHeight()
table.insert(rects, {x = selX, y = selY, width = selWidth, height = selHeight}) table.insert(rects, { x = selX, y = selY, width = selWidth, height = selHeight })
end end
return rects return rects
@@ -5062,7 +5104,7 @@ function Element:_getSelectionRects(selStart, selEnd)
local selY = visualLineNum * lineHeight local selY = visualLineNum * lineHeight
local selHeight = lineHeight local selHeight = lineHeight
table.insert(rects, {x = selX, y = selY, width = selWidth, height = selHeight}) table.insert(rects, { x = selX, y = selY, width = selWidth, height = selHeight })
end end
visualLineNum = visualLineNum + 1 visualLineNum = visualLineNum + 1
@@ -5090,7 +5132,7 @@ function Element:_getSelectionRects(selStart, selEnd)
local selY = visualLineNum * lineHeight local selY = visualLineNum * lineHeight
local selHeight = lineHeight local selHeight = lineHeight
table.insert(rects, {x = selX, y = selY, width = selWidth, height = selHeight}) table.insert(rects, { x = selX, y = selY, width = selWidth, height = selHeight })
visualLineNum = visualLineNum + 1 visualLineNum = visualLineNum + 1
end end
else else