cleaned up rendering mode swapping
This commit is contained in:
@@ -188,6 +188,24 @@ end
|
||||
---@param props ElementProps
|
||||
---@return Element
|
||||
function Element.new(props)
|
||||
-- Early check: If this is a retained-mode element in an immediate-mode context,
|
||||
-- check if it already exists (was restored to parent) to prevent duplicates
|
||||
local elementMode = props.mode
|
||||
if elementMode == nil then
|
||||
elementMode = Element._Context._immediateMode and "immediate" or "retained"
|
||||
end
|
||||
|
||||
-- If retained mode and has an ID, check if element already exists in parent's children
|
||||
if elementMode == "retained" and props.id and props.id ~= "" and props.parent then
|
||||
-- Check if this element already exists in parent's restored children
|
||||
for _, child in ipairs(props.parent.children) do
|
||||
if child.id == props.id and child._elementMode == "retained" then
|
||||
-- Element already exists (was restored), return existing instance
|
||||
return child
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local self = setmetatable({}, Element)
|
||||
|
||||
-- Create dependency subsets for sub-modules (defined once, used throughout)
|
||||
@@ -272,11 +290,56 @@ function Element.new(props)
|
||||
self.children = {}
|
||||
self.onEvent = props.onEvent
|
||||
|
||||
-- Auto-generate ID in immediate mode if not provided
|
||||
if self._elementMode == "immediate" and (not props.id or props.id == "") then
|
||||
-- Track whether ID was auto-generated (before ID assignment)
|
||||
local idWasAutoGenerated = not props.id or props.id == ""
|
||||
|
||||
-- Auto-generate ID if not provided (for all elements)
|
||||
if idWasAutoGenerated then
|
||||
self.id = Element._StateManager.generateID(props, props.parent)
|
||||
else
|
||||
self.id = props.id or ""
|
||||
self.id = props.id
|
||||
end
|
||||
|
||||
-- AFTER ID is determined, check for duplicate top-level OR child retained elements
|
||||
-- ONLY for auto-generated IDs (same call site recreating same element)
|
||||
-- If user provides explicit ID, they control uniqueness
|
||||
if self._elementMode == "retained" and idWasAutoGenerated and self.id and self.id ~= "" then
|
||||
if not props.parent then
|
||||
-- Top-level element: check in topElements
|
||||
for _, existingElement in ipairs(Element._Context.topElements) do
|
||||
if existingElement.id == self.id and existingElement._elementMode == "retained" then
|
||||
-- Element already exists (was preserved from previous frame), return existing instance
|
||||
-- CRITICAL: Clear children array to prevent accumulation
|
||||
-- Children will be re-declared this frame (retained children will be found via duplicate check)
|
||||
existingElement.children = {}
|
||||
return existingElement
|
||||
end
|
||||
end
|
||||
else
|
||||
-- Child element: check in parent's children
|
||||
for _, existingChild in ipairs(props.parent.children) do
|
||||
if existingChild.id == self.id and existingChild._elementMode == "retained" then
|
||||
-- Element already exists (was restored to parent), return existing instance
|
||||
-- CRITICAL: Clear children array to prevent accumulation
|
||||
-- Children will be re-declared this frame (retained children will be found via duplicate check)
|
||||
existingChild.children = {}
|
||||
return existingChild
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- In immediate mode, restore retained children from StateManager
|
||||
-- This allows retained-mode children to persist when immediate-mode parents recreate
|
||||
if self._elementMode == "immediate" and self.id and self.id ~= "" then
|
||||
local retainedChildren = Element._StateManager.getRetainedChildren(self.id)
|
||||
if retainedChildren and #retainedChildren > 0 then
|
||||
-- Restore retained children and update their parent references
|
||||
for _, child in ipairs(retainedChildren) do
|
||||
child.parent = self
|
||||
table.insert(self.children, child)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
self.userdata = props.userdata
|
||||
@@ -2237,6 +2300,11 @@ function Element:destroy()
|
||||
-- Clear children table
|
||||
self.children = {}
|
||||
|
||||
-- Clear retained children from StateManager (if this is an immediate-mode element)
|
||||
if self._elementMode == "immediate" and self.id and self.id ~= "" then
|
||||
Element._StateManager.clearRetainedChildren(self.id)
|
||||
end
|
||||
|
||||
-- Clear parent reference
|
||||
if self.parent then
|
||||
self.parent = nil
|
||||
@@ -3503,6 +3571,12 @@ function Element:saveState()
|
||||
state._textDragOccurred = self._textDragOccurred
|
||||
end
|
||||
|
||||
-- Save retained children references (for mixed-mode trees)
|
||||
-- Only save if this is an immediate-mode element with retained children
|
||||
if self._elementMode == "immediate" and #self.children > 0 then
|
||||
Element._StateManager.saveRetainedChildren(self.id, self.children)
|
||||
end
|
||||
|
||||
return state
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user