{"id":14389,"date":"2026-06-17T11:41:02","date_gmt":"2026-06-17T09:41:02","guid":{"rendered":"https:\/\/store.algosyntax.com\/?post_type=documentation&#038;p=14389"},"modified":"2026-06-17T11:45:43","modified_gmt":"2026-06-17T09:45:43","slug":"linegridcanvaspanel-2-3-child-widget-pools","status":"publish","type":"documentation","link":"https:\/\/store.algosyntax.com\/documentation\/linegridcanvaspanel-2-3-child-widget-pools\/","title":{"rendered":"LineGridCanvasPanel 2.3 | Child Widget Pools"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-post\" data-elementor-id=\"14389\" class=\"elementor elementor-14389\" data-elementor-post-type=\"documentation\">\n\t\t\t\t<div class=\"elementor-element elementor-element-ca24e3c e-flex e-con-boxed e-con e-parent\" data-id=\"ca24e3c\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-3fa12a9 elementor-widget elementor-widget-heading\" data-id=\"3fa12a9\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t\t<h1 class=\"elementor-heading-title elementor-size-default\">LineGridCanvasPanel 2.3: The Widget Pool System<\/h1>\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-c255d1a elementor-widget elementor-widget-text-editor\" data-id=\"c255d1a\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\t<p>The pool sytem is exposed through API endpoints. It does <strong>not<\/strong> automatically rewrite every child workflow by itself. The base class gives future <code>SpawnInViewWidgets()<\/code> \/ <code>RemoveOutOfViewWidgets()<\/code> implementations a clean way to opt into pooling.<\/p><p>With <code>bUseWidgetPool = true<\/code>:<\/p><p><code>AcquireChildWidgetFromPool(Class, DataObject)<\/code> does this:<\/p><ol start=\"1\"><li>Checks <code>ObjectToSmartChildWidgetMap<\/code> first.<\/li><li>If that <code>DataObject<\/code> already has an active widget, returns it.<\/li><li>Otherwise checks the pool bucket for the exact widget class.<\/li><li>If a pooled widget exists, reuses it.<\/li><li>If not, calls <code>CreateWidget<\/code>.<\/li><li>Calls <code>SetDataObject(DataObject)<\/code> before registration.<\/li><li>Calls the child acquire hook.<\/li><li>Calls <code>AddAndRegisterSmartWidget<\/code>.<\/li><li>Requests child layout refresh.<\/li><\/ol>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-c5477de elementor-widget elementor-widget-text-editor\" data-id=\"c5477de\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\t<p><code>ReleaseChildWidgetToPool(Child)<\/code> does this:<\/p><ol start=\"1\"><li>Verifies the child is actively registered under its current <code>GetDataObject()<\/code>.<\/li><li>Calls <code>DeRegisterSmartChild<\/code>, removing it from the canvas and <code>ObjectToSmartChildWidgetMap<\/code>.<\/li><li>Calls the child release hook.<\/li><li>Clears the data object with <code>SetDataObject(nullptr)<\/code>.<\/li><li>Stores it in the exact class bucket only if that bucket is below its max.<\/li><li>If the bucket is full, the widget is dropped and can be garbage collected.<\/li><\/ol>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-2bdf90b elementor-widget elementor-widget-text-editor\" data-id=\"2bdf90b\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\t<p>With <code>bUseWidgetPool = false<\/code>:<\/p><p>You can still call the same API, but it behaves like a non-retaining lifecycle.<\/p><p><code>AcquireChildWidgetFromPool(...)<\/code> still:<\/p><ul><li>checks the active map first,<\/li><li>then creates a widget if needed.<\/li><\/ul><p>But it does <strong>not<\/strong> reuse inactive pooled widgets.<\/p><p><code>ReleaseChildWidgetToPool(...)<\/code> still:<\/p><ul><li>deregisters safely,<\/li><li>clears the data object,<\/li><li>calls the child release hook,<\/li><\/ul><p>but it does <strong>not<\/strong> store the widget for reuse.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-ee02812 elementor-widget elementor-widget-text-editor\" data-id=\"ee02812\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\t<p>So if someone does not want pooling, they can either:<\/p><ul><li>set <code>bUseWidgetPool = false<\/code> and still use the same acquire\/release API, or<\/li><li>ignore the pool API completely and use <code>CreateWidget<\/code>, <code>AddAndRegisterSmartWidget<\/code>, and <code>DeRegisterSmartChild<\/code> manually.<\/li><\/ul><p>The intended pooled virtualization pattern is:<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-c7a1c38 elementor-widget elementor-widget-code-highlight\" data-id=\"c7a1c38\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"code-highlight.default\">\n\t\t\t\t\t\t\t<div class=\"prismjs-default copy-to-clipboard \">\n\t\t\t<pre data-line=\"\" class=\"highlight-height language-cpp line-numbers\">\n\t\t\t\t<code readonly=\"true\" class=\"language-cpp\">\n\t\t\t\t\t<xmp>RemoveOutOfViewWidgets(...)\r\n{\r\n    \/\/ For active children no longer in view:\r\n    ReleaseChildWidgetToPool(Child);\r\n}\r\n\r\nSpawnInViewWidgets(...)\r\n{\r\n    \/\/ For data objects now in view:\r\n    if (!GetActiveLineGridChildWidgetForDataObject(DataObject))\r\n    {\r\n        Child = AcquireChildWidgetFromPool(WidgetClass, DataObject);\r\n        \/\/ configure logical spans \/ visuals\r\n    }\r\n}<\/xmp>\n\t\t\t\t<\/code>\n\t\t\t<\/pre>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"featured_media":0,"template":"elementor_header_footer","categories":[132,129],"tags":[133,136],"class_list":["post-14389","documentation","type-documentation","status-publish","hentry","category-enhanced-ui","category-unreal-engine","tag-user-interface","tag-userinterface","entry"],"acf":[],"_links":{"self":[{"href":"https:\/\/store.algosyntax.com\/asx-rest\/wp\/v2\/documentation\/14389","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/store.algosyntax.com\/asx-rest\/wp\/v2\/documentation"}],"about":[{"href":"https:\/\/store.algosyntax.com\/asx-rest\/wp\/v2\/types\/documentation"}],"version-history":[{"count":2,"href":"https:\/\/store.algosyntax.com\/asx-rest\/wp\/v2\/documentation\/14389\/revisions"}],"predecessor-version":[{"id":14394,"href":"https:\/\/store.algosyntax.com\/asx-rest\/wp\/v2\/documentation\/14389\/revisions\/14394"}],"wp:attachment":[{"href":"https:\/\/store.algosyntax.com\/asx-rest\/wp\/v2\/media?parent=14389"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/store.algosyntax.com\/asx-rest\/wp\/v2\/categories?post=14389"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/store.algosyntax.com\/asx-rest\/wp\/v2\/tags?post=14389"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}