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,10 +629,19 @@ function Element.new(props)
self.width = tempWidth
else
self.autosizing.width = true
-- Calculate auto-width without padding first
tempWidth = self:calculateAutoWidth()
self.width = tempWidth
self.units.width = { value = nil, unit = "auto" } -- Mark as auto-sized
-- 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
tempWidth = self:calculateAutoWidth()
self.width = tempWidth
self.units.width = { value = nil, unit = "auto" } -- Mark as auto-sized
end
end
-- Handle height (both h and height properties, prefer h if both exist)
@@ -1970,17 +1979,43 @@ function Element:addChild(child)
-- 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
local sizeChanged = false
if self.autosizing.height then
local oldHeight = self.height
local contentHeight = self:calculateAutoHeight()
-- BORDER-BOX MODEL: Add padding to get border-box, then subtract to get content
self._borderBoxHeight = contentHeight + self.padding.top + self.padding.bottom
self.height = contentHeight
if oldHeight ~= self.height then
sizeChanged = true
end
end
if self.autosizing.width then
local oldWidth = self.width
local contentWidth = self:calculateAutoWidth()
-- BORDER-BOX MODEL: Add padding to get border-box, then subtract to get content
self._borderBoxWidth = contentWidth + self.padding.left + self.padding.right
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
@@ -3854,6 +3889,13 @@ function Element:calculateTextHeight()
if self.textWrap and (self.textWrap == "word" or self.textWrap == "char" or self.textWrap == true) then
-- Calculate available width for wrapping
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
-- Get the wrapped text lines using getWrap (returns width and table of lines)
local wrappedWidth, wrappedLines = font:getWrap(self.text, availableWidth)
@@ -4674,7 +4716,7 @@ function Element:_wrapLine(line, maxWidth)
type = "space",
text = line:sub(utf8.offset(line, wsStart), utf8.offset(line, pos) and utf8.offset(line, pos) - 1 or #line),
startPos = wsStart - 1,
length = pos - wsStart
length = pos - wsStart,
})
else
-- Collect word (non-whitespace sequence)
@@ -4686,13 +4728,13 @@ function Element:_wrapLine(line, maxWidth)
type = "word",
text = line:sub(utf8.offset(line, wordStart), utf8.offset(line, pos) and utf8.offset(line, pos) - 1 or #line),
startPos = wordStart - 1,
length = pos - wordStart
length = pos - wordStart,
})
end
end
-- Process tokens and wrap
local charPos = 0 -- Track our position in the original line
local charPos = 0 -- Track our position in the original line
for i, token in ipairs(tokens) do
if token.type == "word" then
local testLine = currentLine .. token.text
@@ -4987,7 +5029,7 @@ function Element:_getSelectionRects(selStart, selEnd)
local selY = 0
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
return rects
@@ -5062,7 +5104,7 @@ function Element:_getSelectionRects(selStart, selEnd)
local selY = visualLineNum * 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
visualLineNum = visualLineNum + 1
@@ -5090,7 +5132,7 @@ function Element:_getSelectionRects(selStart, selEnd)
local selY = visualLineNum * 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
end
else