|
|
tl;dr Proposal to add Fl_Widget::resizable(int width_factor,
int height_factor) and merge Fl_Flex into Fl_Pack.
I was looking into how Fl_Flex differs from Fl_Pack, and apart
from the margins, Fl_Flex adds the option the make individual
children resizable while the rest stays fixed. So instead of
introducing a new widget, wouldn't it be better to add this
functionality to Fl_Pack?
No. Fl_Pack has some properties that differ from Fl_Flex and all
other widgets and groups: Fl_Pack "shrink-wraps" itself around its
children, and it does this during its draw() method which leads to
all sorts of unexpected behavior. You can't really say that an
Fl_Pack has a pre-determined size because of this "feature".
Fl_Pack also uses the resizable() widget in a very special way that
is not used elsewhere and leads to unpredictable behavior,
particularly in nested Fl_Pack widgets.
Fl_Flex is a better alternative to Fl_Pack because it doesn't have
all these IMHO negative properties. You can give it a specific size
and it fills its space with its children. The *standard*
behavior is "flexible", i.e. all children adjust their sizes to the
available space, not vice versa. The *exception* is to give
some widgets a fixed size for special layout options.
If we could choose I would remove Fl_Pack and use Fl_Flex instead as
the new "Fl_Pack" widget. However, changing Fl_Pack is not an
option, and that's why I "ported" the existing Fl_Flex widget to
FLTK as an alternative and Fl_Pack should be considered deprecated.
The design and API of Fl_Flex have in parts been chosen such that it
can be used as a drop-in replacement of Fl_Pack without Fl_Pack's
problems. Hopefully.
Fl_Pack may be used in existing programs, and therefore we should
keep it as is to avoid backwards compatibility issues.
Which brings me to the second point.
Fl_Group::resizable(Fl_Widget*) is a horrible interface. First
of all, we reference a child widget, wich may disappear, giving
us a dangling pointer. Second of all, we can only have one
resizable child, which generated the need for Fl_Flex.
Yep, maybe. But that's not a bug, it's a "feature" since FLTK 1.0,
isn't it? And it works...
Now, Fl_Flex maintains a list of children that are resizable,
and the list is not updated if children are removed because
Fl_Group::remove() and clear() are not virtual (delete_child()
is, but that is not enough). Again, we get dangling pointers.
That's true, as it is now, and it is a known problem. I have been
working on a general solution to be applied to Fl_Group and
inherited by Fl_Flex and other derived widget to overcome this
issue. Unfortunately helping to get the Wayland support working
distracted me and this work was not yet applied to Fl_Flex although
it's almost ready.
My proposal is to remove Fl_Group::resizable_ and instead add
either a flag or an integer to Fl_Widget to indicate if the
widget is resizable (flag) or even better, by what factor a
widget is resizable (int). Adding the functionality of Fl_Flex
to Fl_Pack would be ten lines of code.
I strongly recommend NOT to change Fl_Pack at all. As said above,
leave it as is for backwards compatibility and get rid of its odd
behavior for new development.
Fl_Group::resizable(Fl_Widget*) could be implemented with the
exact same API and functionality, but without the risk of
dangling pointers.
Fl_Group does already "know about" deleted widgets and if it doesn't
take the deletion of the resizable() widget into account that is
probably a bug. It would be easy to do this, however the decision
would be harder: what should be done?
Option one: set resizable(0) which would make the Fl_Group widget no
longer reiszable.
Option two: set resizable(this) seems the more appropriate option
which would leave the group resizable.
I suggest to discuss options to implement a feature to observe
widget deletion in a separate thread. I'd like to see your (and
others') comments on my proposal and we should find a proper way
Since the resizable() method name is already taken, we need a
new method name. We could use Fl_Widget::flexible(bool), but how
about Fl_Widget::resizable(int width, int height) where width
and height are factors in the given direction. It's a bit of a
stretch, as Fl_Group::resizable(child) would be the same as
child->resizable(100, 100), but it can't all be perfect. This
would add two integers, eight bytes, to every Fl_Widget, and
remove one pointer from Fl_Group and more pointers from
Fl_Pack/Fl_Flex.
If we had both these features, i.e. Fl_Group::resizable(Fl_Widget *)
and Fl_Widget::resizable(...) then we would likely have a
contradiction if both is given. Which one would determine the
resizing algorithm of the group? I don't see (at a first glance) how
this could be resolved - and it would make the resizing algorithm
even more complicated. Note that neither Fl_Flex nor Fl_Grid (see
below) use the resizable() widget (it's entirely ignored).
That said, besides Fl_Flex I'm still working on Fl_Grid which
provides even more flexibility to the resizing of widgets inside the
grid container. It's like a two-dimensional Fl_Flex or HTML
<table> with options of overlapping widgets like HTML
`colspan` and `rowspan` attributes. This Fl_Grid widget is also on
the "Release 1.4.0" milestone and almost ready to go.
I'm sure I can resolve the "dangling pointers" issue in both widgets
- and in some other core widgets. My proposal would be usable in
derived classes as well. @Matthias: I sent you a proposal a while
ago but I changed it meanwhile a little bit. The basics are the same
though.
Many users have requested better layout widgets, and Fl_Flex has
even already been integrated in fltk-rs (Rust bindings for FLTK).
Summary (my conclusion):
Fl_Flex and Fl_Grid provide the requested better layout widgets w/o
touching the "standard" FLTK resizing algorithm and should be added
because they are really needed. Touching Fl_Pack would open a can of
worms and should be avoided.
Everything else can and should be discussed after the release of
FLTK 1.4.0.
--
You received this message because you are subscribed to the Google Groups "fltk.coredev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to fltkcoredev+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/fltkcoredev/5ab5e3a1-aaa9-1df6-4d51-3cb50837f676%40online.de.
[ Direct Link to Message ] | |
|
| |