Albrecht Schlosser schrieb am Donnerstag, 27. Oktober 2022 um 14:58:20 UTC+2:
The Group thing is quite easy to resolve: we just need to make
Fl_Group::insert(), remove(), and clear() virtual.
Unfortunately not. Been there, "tried" that, but it can't work
because we have too many overloaded add(), remove() and clear() and
maybe also insert() methods with entirely unrelated semantics.
I just checked. The union of child1_ and array_ is only written in Fl_Group::insert(Fl_Widget*, int index) and Fl_Group::remove(int index) and nowhere else. Fl_Group::erase() accesses it via array() in the most heinous of ways. Fl_Scroll and Fl_Tree reshuffle children, but at least do not add or remove any. Fl_Table does its own thing anyway (sigh). Everything else just reads array(). So I think insert, remove, and clear are good enough. Fl_Group::array() should be deprecated, disable, curried, and removed.
This needs just a few lines of code to be implemented:
in Fl_Widget at the top:
if (when() &
FL_WHEN_DELETING) {
int old_event = Fl::event();
Fl::event(FL_DELETING);
do_callback();
Fl::event(old_event);
}
plus the declaration of those constants and some Fluid
changes.
Where "in Fl_Widget" would this be implemented? I assume you mean in
~Fl_Widget(), i.e. in the destructor. Or did you mean the handle()
method? Anyway, assuming correct implementation:
In ~Fl_Widget as one of the first lines to keep much of Fl_Widget in tact. But it doesn't;t really matter as it is really only there to avoid deriving a new class. If a new class is derived, this code can go into the destructor anyway. Also, doe we really need thin in ::handle()? Because, if a new widget is created anyway to have a new handle() method, why not again just put that code in the destructor. It doesn't really do any harm either, so, eh?
+1
There's one remaining problem though, if I'm not missing anything.
Your example seems perfect, but I believe at the time the destructor
of Fl_Widget is called, the derived class would already be partially
destroyed. Hence we need to document clearly that the callback would
only be allowed to deallocate the related (user) data but not access
the widget, i.e. any parts of the derived class. Or whatever.
Yes, that's correct, and it's one reason why it should only be available in the callback, to make clear that that is really the main (and only?) purpose. It could bused to clear external links *to* that widget, but that's a bit of a stretch.
Fl_Widget::copy_label() does indeed make a copy of a string and the
previous owner of the string can free it immediately. Hence the name
`copy...`.
Yes, my example was not a good match. I just wanted to illustrate that we can have a label that is automatically free'd when the widget goes, and we could also have user_data that can be marked to be automatically free'd or deleted.