RFC: Fl_Group option with relative coords for children

30 views
Skip to first unread message

Greg Ercolano

unread,
Nov 26, 2020, 11:18:19 AM11/26/20
to fltk.coredev
Now that we have the ability to apply transformations to fltk drawing (I think?),
would it make sense to add a method to Fl_Group, e.g. relative(bool) that allows child widgets
to be positioned relative to the upper/left corner of the group rather than the parent window?
Much like the way one can use subwindows now, but without the window-related overhead that can entail.

Seems like it'd be easy for the draw() code to do something like:

void Fl_Group::draw() {
  // Relative positioning of children? translate coord space to our x()/y()
  if ( relative() ) fl_translate(x(), y());
  // Draw the children
  [..]
  // Undo transform..
  if ( relative() ) fl_translate(-x(), -y());   // basically 'pop' the old transforms
}

I think event x/y positions could be translated too by adjusting x/y events
on entry to the Fl_Group::handle() method, and undoing them on exit.

Might involve mods to FLTK's core to support event delivery for focus widgets though,
since those get a first shot at events and bypass the widget handle() hierarchy by directing
events directly at the focus widget first. For that to work, FLTK's core event delivery would
have to walk the widget hierarchy looking for Fl_Groups with this relative() flag on, so it can
calculate an offset for the events.

Anyway, just a thought -- I'm not sure this would work and haven't tried any tests, just curious
if this sounds plausible/useful, or is just an unwanted can of worms or a malformed idea..

Gonzalo Garramuño

unread,
Nov 26, 2020, 4:37:59 PM11/26/20
to fltkc...@googlegroups.com

El 26/11/20 a las 13:18, Greg Ercolano escribió:
> Anyway, just a thought -- I'm not sure this would work and haven't tried any tests, just curious
> if this sounds plausible/useful, or is just an unwanted can of worms or a malformed idea..
>
It sounds like a can of worms to me.  You would then have to check on
people's code whether they are drawing relatively or not and same for
the events.

I would vote a -1.

Greg Ercolano

unread,
Nov 26, 2020, 5:31:56 PM11/26/20
to fltkc...@googlegroups.com
    Just curious; is that different from using Fl_Window as a subwindow?
    Same behavior, just in an Fl_Group..

Gonzalo Garramuño

unread,
Nov 26, 2020, 6:01:22 PM11/26/20
to fltkc...@googlegroups.com

El 26/11/20 a las 19:31, Greg Ercolano escribió:
>     Just curious; is that different from using Fl_Window as a subwindow?
>     Same behavior, just in an Fl_Group..
I think the subwindow is more clear, while with the Fl_Group you can get
caught off-guard.  But maybe I am mistaken.  Would like to hear more
about the use of this feature.

Ian MacArthur

unread,
Nov 26, 2020, 6:06:14 PM11/26/20
to coredev fltk
On 26 Nov 2020, at 16:18, Greg Ercolano wrote:
>
> Now that we have the ability to apply transformations to fltk drawing (I think?),


Do we?
ISTR that “historically” the “fast” drawing methods (which we use a fair bit internally) are not specified to obey the transformation matrices... Though that may no longer be the case, of course.
I do not know.
If they do not (and they certainly did not, in the past; or at least not consistently across systems) then I do not think this could work.

Or I could be talking nonsense...





Albrecht Schlosser

unread,
Nov 26, 2020, 7:28:37 PM11/26/20
to fltkc...@googlegroups.com
On 11/27/20 12:06 AM Ian MacArthur wrote:
> On 26 Nov 2020, at 16:18, Greg Ercolano wrote:
>>
>> Now that we have the ability to apply transformations to fltk drawing (I think?),

That's not a sentence I'd start with "Now ...", this is old stuff and is
already documented in FLTK 1.1 - see below.

> Do we?
> ISTR that “historically” the “fast” drawing methods (which we use a fair bit internally) are not specified to obey the transformation matrices... Though that may no longer be the case, of course.
> I do not know.
> If they do not (and they certainly did not, in the past; or at least not consistently across systems) then I do not think this could work.

Right, this is so by definition (i.e. it's documented). The docs often
say that the behavior is undefined if the transformation is not the
identity.

See "Drawing Fast Shapes" in chapter "Drawing Things in FLTK" and
"Drawing Images" in the same chapter:

```
Direct Image Drawing

The behavior when drawing images when the current transformation matrix
is not the identity is not defined, so you should only draw images when
the matrix is set to the identity.
```

FLTK 1.1 (!) docs:
https://www.fltk.org/doc-1.1/drawing.html#images

Whether it works one or the other way I cannot say, but the
documentation ("undefined behavior") leaves more freedom to the
implementation which can simplify things a lot.

Albrecht Schlosser

unread,
Nov 26, 2020, 7:47:14 PM11/26/20
to fltkc...@googlegroups.com
On 11/26/20 11:31 PM Greg Ercolano wrote:
> On 2020-11-26 13:37, Gonzalo Garramuño wrote:
>> El 26/11/20 a las 13:18, Greg Ercolano escribió:
>>> Anyway, just a thought -- I'm not sure this would work and haven't tried any tests, just curious
>>> if this sounds plausible/useful, or is just an unwanted can of worms or a malformed idea..

(see my other post about drawing coordinate transformations)

>> It sounds like a can of worms to me.  You would then have to check on
>> people's code whether they are drawing relatively or not and same for
>> the events.

Well, all the drawing code goes through FLTK drawing functions, hence it
would be possible somehow, but not by means of the coordinate
transformation matrix.

>> I would vote a -1.

It's definitely too big a project for anything in the near future like
FLTK 1.4 IMHO.

<history> Matt had to deal with this in his attempt do combine FLTK 1
(absolute/window coordinates) and FLTK 2 (group relative coordinates) in
one system (FLTK 3) which didn't succeed, although I imagine that he had
solved the coordinate issue with some tricks...
</history>

>     Just curious; is that different from using Fl_Window as a subwindow?
>     Same behavior, just in an Fl_Group..

That's a *giant* difference. Fl_Group widgets are just containers of the
main window and all drawing primitives use the window coordinates which
are known to the OS. It's simple, Fast and Light.

Fl_Window's have their own coordinate systems because they are
represented by their own OS window objects.

This is true at least for X11 and Windows but I'm not sure if it's also
true for macOS. I believe it's not but Manolo can certainly tell us.

This means that a subwindow is no different than a main window WRT
drawing from FLTK's POV. The only difference is that the creator of
widgets (i.e. the programmer) needs to know which window is the
reference (coordinate 0,0) to position the widgets.

Albrecht Schlosser

unread,
Nov 26, 2020, 8:59:24 PM11/26/20
to fltkc...@googlegroups.com
On 11/26/20 5:18 PM Greg Ercolano wrote:
> [...]
> would it make sense to add a method to Fl_Group, e.g. relative(bool) that allows child widgets
> to be positioned relative to the upper/left corner of the group rather than the parent window?
> [...]
> Anyway, just a thought -- I'm not sure this would work and haven't tried any tests, just curious
> if this sounds plausible/useful, or is just an unwanted can of worms or a malformed idea..

Here's a thought that *could* work: long ago I created a commercial
application that used group relative coordinates in its own
window/group/widget definition syntax. These internal group relative
coordinates wer transformed to FLTK window relative coordinates when the
widgets were created.

What we could do is a similar approach: we could use a flag that lets
the user create a widget with group relative coordinates and we could
transform the widget coordinates to window relative coordinates when the
widget is add()ed to the group. This flag could either be global or used
in a modified Fl_Group::add() method.

Example:

Fl_Group::add_relative(1); // set relative coordinates

Fl_Window *win = new Fl_Window(600, 400);

Fl_Group *grp = new Fl_Group(100, 100, 200, 200); // (100, 100)

Fl_Input *inp = new Fl_Input(20, 30, 100, 30); // 120, 130

Adding the Fl_Input to the group at (100, 100) with relative coordinates
(20, 30) would transform the coordinates to (100+20, 100+30) when the
widget gets added to the group.

The good thing is that this would only need changes to Fl_Group::add()
and similar (Fl_Group) methods but no changes to drawing and event
delivery and it would be entirely optional (applicable per widget /
group if necessary).

Might be worth some further investigations...

Greg Ercolano

unread,
Nov 26, 2020, 9:27:44 PM11/26/20
to fltkc...@googlegroups.com
On 2020-11-26 17:59, Albrecht Schlosser wrote:
> Here's a thought that *could* work: long ago I created a commercial
> application that used group relative coordinates in its own
> window/group/widget definition syntax. These internal group relative
> coordinates wer transformed to FLTK window relative coordinates when the
> widgets were created.
>
> What we could do is a similar approach: we could use a flag that lets
> the user create a widget with group relative coordinates and we could
> transform the widget coordinates to window relative coordinates when the
> widget is add()ed to the group. This flag could either be global or used
> in a modified Fl_Group::add() method.
> [..]
> Might be worth some further investigations...

    Interesting -- and if Gonzalo's issue is a concern worth addressing (confusion over absolute vs. relative),
    it could be a subclass, e.g. Fl_Group_R or Fl_Group_Relative or some such. We certainly have cases
    where a whole class is used just to set a flag (e.g. Fl_Output).

    I guess the good thing though about using the transforms in draw() is that interrogating the children's
    xywh values while in the group would retrieve the same values they were created with.

    I wasn't sure if transforms were fully implemented, as I don't think they affect /all/ fltk drawing code,
    just some, but perhaps that's been fixed during the recent mods for drivers and scaling.

    Certainly it's useful to be able to create widgets relative to the upper-left of the parent that is not a window;
    doing form layouts in fluid that are then procedurally instanced in a scroll is one of many I can think of.
    I usually have to go in after and apply x/y offsets.


Manolo

unread,
Nov 27, 2020, 3:21:12 AM11/27/20
to fltk.coredev
Child Fl_Window objects are (since 1.3) true OS windows under macOS just as they are
under Windows and X11.

Albrecht Schlosser

unread,
Nov 28, 2020, 8:12:47 AM11/28/20
to fltkc...@googlegroups.com
On 11/27/20 3:27 AM Greg Ercolano wrote:
> On 2020-11-26 17:59, Albrecht Schlosser wrote:
>> Here's a thought that *could* work: long ago I created a commercial
>> application that used group relative coordinates in its own
>> window/group/widget definition syntax. These internal group relative
>> coordinates wer transformed to FLTK window relative coordinates when the
>> widgets were created.
>>
>> What we could do is a similar approach: we could use a flag that lets
>> the user create a widget with group relative coordinates and we could
>> transform the widget coordinates to window relative coordinates when the
>> widget is add()ed to the group. This flag could either be global or used
>> in a modified Fl_Group::add() method.
>> [..]
>> Might be worth some further investigations...
>
>     Interesting -- and if Gonzalo's issue is a concern worth addressing (confusion over absolute vs. relative),
>     it could be a subclass, e.g. Fl_Group_R or Fl_Group_Relative or some such. We certainly have cases
>     where a whole class is used just to set a flag (e.g. Fl_Output).

These classes (like Fl_Output) are only a few exceptions, but your idea
would concern all classes. Inheritance would be a mess. Think of
Fl_Tabs_R: what should be its base class, Fl_Group or Fl_Group_R ? And
so on, this is only a very simple example.

>     I guess the good thing though about using the transforms in draw() is that interrogating the children's
>     xywh values while in the group would retrieve the same values they were created with.

Hmm, I can't see the "good thing" in this. Honestly.

Whenever you resize the window or a group within the window all
contained widgets get new x/y/w/h values anyway. I'd say this (returning
relative coordinates) would be more confusing than good.

>     I wasn't sure if transforms were fully implemented, as I don't think they affect /all/ fltk drawing code,
>     just some, but perhaps that's been fixed during the recent mods for drivers and scaling.

I'm 99.9% sure that the driver stuff didn't change the fact that the
transformations are not obeyed by all drawing functions.

<tl;dr>

In a very simplified form the implementations of drawing functions have
"only" been moved to different source files. Instead of:

void fl_draw_something() {
#if defined(_WIN32)
// platform specific implementation here
#elif defined(__APPLE__)
// platform specific implementation here
#else
// platform specific implementation here
#endif
}

we have now:

void fl_draw_something() {
fl_graphics_driver->draw_something();
}

with draw_something() being implemented in platform specific source
files as virtual driver methods and fl_graphics_driver being the current
platform specific graphics driver. The implementation was not affected
by this move.

</tl;dr>

>     Certainly it's useful to be able to create widgets relative to the upper-left of the parent that is not a window;
>     doing form layouts in fluid that are then procedurally instanced in a scroll is one of many I can think of.
>     I usually have to go in after and apply x/y offsets.

I agree that this would be a useful addition, but I believe that the
internal storage of x/y coordinates should not be changed for several
(implementation) reasons and "F" (fast) property of FLTK.

I believe the only thing needed would be an option to create widgets
with x/y coordinates relative to their parents and to add() or insert()
widgets into groups with x/y relative to their group (parent) coordinates.

This would probably require new constructors (for /all/ widgets) with a
flag to use x/y as relative to their parents, as in

// main()
const int rel = 1;
Fl_Window win(400, 400);
Fl_Group grp(50, 50, 300, 300);
Fl_Box box(10, 20, 80, 80, rel, "label");

so we can also support static constructors as shown above. In this case
x/y of box would be relative to its parent grp, i.e. x = 60, y = 70.

If you want to get relative coordinates of widgets you can (alreay now) use:

int rel_x = box.x() - box.parent()->x();

or we could easily add

int Fl_Widget::rel_x() {
if (parent())
return x() - parent()->x();
else
return x();
}

Albrecht Schlosser

unread,
Nov 28, 2020, 8:23:30 AM11/28/20
to fltkc...@googlegroups.com
Continuation of previous post:

On 11/28/20 2:12 PM Albrecht Schlosser wrote:
> On 11/27/20 3:27 AM Greg Ercolano wrote:

>>      Certainly it's useful to be able to create widgets relative to
>> the upper-left of the parent that is not a window;
>>      doing form layouts in fluid that are then procedurally instanced
>> in a scroll is one of many I can think of.
>>      I usually have to go in after and apply x/y offsets.

fluid is IMHO a completely different and complex story. What code should
it generate, relative or absolute coordinates?

We could probably add a new flag (check box) to the widget properties to
mark the widget as "relative" or something like that. But I don't know
fluid code enough to see all the possible implications (and
complications ;-) ).

imm

unread,
Nov 28, 2020, 10:33:20 AM11/28/20
to coredev fltk
On Sat, 28 Nov 2020, 13:23 Albrecht Schlosser wrote

We could probably add a new flag (check box) to the widget properties to
mark the widget as "relative" or something like that. But I don't know
fluid code enough to see all the possible implications (and
complications ;-) ).

AFAIK fluid already has a check box for deriving a widget with relative coordinates - unless I've missed the point and we're talking about something subtly different?
-- 
Ian
From my Fairphone FP3

Greg Ercolano

unread,
Nov 28, 2020, 11:22:04 AM11/28/20
to fltkc...@googlegroups.com
On 2020-11-28 07:33, imm wrote:
> AFAIK fluid already has a check box for deriving a widget with relative coordinates


    Wouldn't be the first time there was a feature in fluid I didn't know about.. where's that button?

Ian MacArthur

unread,
Nov 28, 2020, 4:51:14 PM11/28/20
to fltkc...@googlegroups.com
Unnecessarily large screen grab attached below; it’s the “Relative” check button on the UserInterface Properties dialog...








-- 
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...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/fltkcoredev/550c3613-8a02-efc9-46c8-aa3f3979254e%40seriss.com.

Greg Ercolano

unread,
Nov 28, 2020, 5:59:48 PM11/28/20
to fltkc...@googlegroups.com
On 2020-11-28 13:51, Ian MacArthur wrote:
> On 28 Nov 2020, at 16:22, Greg Ercolano wrote:
>>
>>     Wouldn't be the first time there was a feature in fluid I didn't know about.. where's that button?
>
> Unnecessarily large screen grab attached below; it’s the “Relative” check button on the UserInterface Properties dialog...


    Hmm, OK, I was looking in the New -> Group -> Group -> properties (where it's not there).

    I guess the important thing to know is it's in the New -> Code -> Widget Class -> properties..!
    Interesting -- guess I'll have to try that out.


Reply all
Reply to author
Forward
0 new messages