diff --git a/doomsday/sdk/libappfw/include/de/framework/childwidgetorganizer.h b/doomsday/sdk/libappfw/include/de/framework/childwidgetorganizer.h index de3a151324..6e7d75b89b 100644 --- a/doomsday/sdk/libappfw/include/de/framework/childwidgetorganizer.h +++ b/doomsday/sdk/libappfw/include/de/framework/childwidgetorganizer.h @@ -124,6 +124,16 @@ class LIBAPPFW_PUBLIC ChildWidgetOrganizer */ void setVirtualizationEnabled(bool enabled); + /** + * Enables or disables child recycling. Deleted children will be put up for + * recycling instead of being deleted, and new children will first be taken + * from the set of old recycled widgets. + * + * It is only possible to use this when all the items being managed have the + * same kind of widget representing them. + */ + void setRecyclingEnabled(bool enabled); + void setVirtualTopEdge(Rule const &topEdge); void setVisibleArea(Rule const &minimum, Rule const &maximum); diff --git a/doomsday/sdk/libappfw/src/childwidgetorganizer.cpp b/doomsday/sdk/libappfw/src/childwidgetorganizer.cpp index 371c428a5c..f1dba8ca73 100644 --- a/doomsday/sdk/libappfw/src/childwidgetorganizer.cpp +++ b/doomsday/sdk/libappfw/src/childwidgetorganizer.cpp @@ -71,6 +71,9 @@ DENG2_PIMPL(ChildWidgetOrganizer) float totalCorrection = 0; float correctionPerUnit = 0; + bool recyclingEnabled = false; + QList recycledWidgets; // Not GL-deinitialized to facilitate fast reuse. + Impl(Public *i, GuiWidget *c) : Base(i) , container(c) @@ -79,6 +82,11 @@ DENG2_PIMPL(ChildWidgetOrganizer) ~Impl() { + foreach (GuiWidget *recycled, recycledWidgets) + { + GuiWidget::destroy(recycled); + } + releaseRef(virtualTop); releaseRef(virtualMin); releaseRef(virtualMax); @@ -130,7 +138,15 @@ DENG2_PIMPL(ChildWidgetOrganizer) ui::Item const &item = dataItems->at(pos); - GuiWidget *w = factory->makeItemWidget(item, container); + GuiWidget *w = nullptr; + if (recyclingEnabled && !recycledWidgets.isEmpty()) + { + w = recycledWidgets.takeFirst(); + } + else + { + w = factory->makeItemWidget(item, container); + } if (!w) return nullptr; // Unpresentable. // Update the widget immediately. @@ -213,7 +229,16 @@ DENG2_PIMPL(ChildWidgetOrganizer) { //pendingStrutAdjust.remove(w); w->audienceForDeletion() -= this; - GuiWidget::destroy(w); + + if (recyclingEnabled) + { + w->orphan(); + recycledWidgets << w; + } + else + { + GuiWidget::destroy(w); + } } void clearWidgets() @@ -580,6 +605,11 @@ void ChildWidgetOrganizer::setVirtualizationEnabled(bool enabled) } } +void ChildWidgetOrganizer::setRecyclingEnabled(bool enabled) +{ + d->recyclingEnabled = enabled; +} + void ChildWidgetOrganizer::setVirtualTopEdge(Rule const &topEdge) { changeRef(d->virtualTop, topEdge);