nanogui
nanogui copied to clipboard
Dynamic Forms: Flexibility of FormHelper/Memory Leak with AdvancedGridLayout
I'm trying to have composable widgets, which may get added or removed based on the underlying data model -- e.g., user adds or removes a shape to a 3d scene, and the form dynamically adds/removes a set of widgets accordingly.
The difficulty I'm having with the FormHelper/AdvancedGridLayout is two fold:
- FormHelper uses specifically a
Windowas the parent widget for all sub widgets AdvancedGridLayoutwill leak memory by maintaining a dangling pointer to any added widgets in it'sm_anchorfield -- there's no way to deregister a widget, and when used in combination withFormHelper, there's no (ergonomic) way to get the address of any label added byFormHelper
I'm going to attempt to create a similar class to FormHelper that allows adding widgets to an arbitrary parent widget, rather than a specific window. My hope is that by having each composite widget maintain it's own AdvancedGridLayout, I can avoid the memory leak because when the composite widget is removed it will destroy the AdvancedGridLayout that has all of the children widgets registered.
I'm curious about the following:
- something that has been encountered/considered before
- are the maintainers interested in any contributions to provide more flexibility? I could imagine the api I describe below being selected via sfinae based on if the parent is a
Window*or not to select the existingFormHelperor a new implementation. I'm open to input on what would make it suitable for a contribution if there's interest. - is what I'm thinking reasonable/am i doing something totally wrong/not considering something? -- I'm fairly new to using nanogui, so I could very well be overlooking some well understood usage pattern.
My widget tree would look something like:
- Screen
- Window:
- Scene Objects:
- SphereForm:
- Label: Min Phi
- FormWidget
- Label: Max Phi
- FormWidget
- FloatBox
- ColorForm:
- Label: Primary Color
- ColorPicker
- ColorForm
- Label: Primary Color
- ColorPicker
- SphereForm:
- Label: Min Phi
- FormWidget
- Label: Max Phi
- FormWidget
- FloatBox
- ColorForm:
- Label: Primary Color
- ColorPicker
- ColorForm
- Label: Primary Color
- ColorPicker
- SphereForm:
- Scene Objects:
- Window:
Ideally my api would look something like:
class FormBuilder {
ref<Widget> m_parent;
public:
FormBuilder(Widget* parent) m_parent(parent) {
parent->set_layout(new AdvancedGridLayout{...})
}
add_widget(const std::string&label, Widget *child);
...misc helpers to mimic the FormHelper api...
};
class SphereForm : public nanogui::Widget {
SphereForm(Widget* parent) : nanogui::Widget(parent) {
auto f = FormBuilder(this);
f->add_widget("Min Phi", new nanogui::detail::FormWidget<float>{});
f->add_widget("Max Phi", new nanogui::detail::FormWidget<float>{});
f->add_widget("Primary Color", new ColorForm{...});
};
};
class SceneWindow : nanogui::Window {
SceneWindow(nanogui::Screen* s) : nanogui::Widnow(s, "Scene Objects") {
add_child(new SphereForm(this));
add_child(new SphereForm(this));
}
}