How to achieve a spaced out layout

153 views
Skip to first unread message

Mark

unread,
Nov 30, 2021, 8:47:41 AM11/30/21
to fltk.general
I want to have a row of buttons like this:

[New] [Options] ...gap... [About] [Help] ...gap... [Quit]

Where the first two are aligned to the left of the parent window, the middle two are in the middle of the row and the last one is on the right. And of course I want them to keep these relative positions when the window is resized.

Can this be done with pack or flex?

wea...@gmail.com

unread,
Nov 30, 2021, 9:04:37 AM11/30/21
to fltk.general
Someone posted a layout manager for FLTK, you can check that out: https://github.com/osen/Fl_Flow 

Albrecht Schlosser

unread,
Nov 30, 2021, 10:05:49 AM11/30/21
to fltkg...@googlegroups.com
I don't think that this can be done with pack (Fl_Pack), you can't define arbitrary and resizing "gaps".

flex (Fl_Flex) is not a core FLTK widget, it is a user contribution added to the rust bindings. I don't know what it can do or not.

With standard FLTK (1.4, git, as of today) I'd derive my own container widget from Fl_Group and override the resize() method.

However, I'm working on a new Fl_Grid widget that can do easily what you want to achieve. This is intended to be in FLTK 1.4.0 when released, hopefully early in the next year (Jan, Feb, Mar?).

I'm attaching a screenshot of two instances of the test/grid_buttons.cxx demo and you can view the source code in my fork (branch Fl_Grid):

https://github.com/Albrecht-S/fltk/blob/Fl_Grid/test/grid_buttons.cxx

PS: I know that @MoAlyousef, the maintainer of fltk-rs, is following the development and I assume that he will add Fl_Grid to the Rust bindings as soon as it is ready for production (i.e. at least in the official FLTK 1.4 branch in git).

grid_buttons.png

imm

unread,
Nov 30, 2021, 10:09:06 AM11/30/21
to General FLTK
It's easier to do this with the fltk default layout mechanism, actually.

The problem with that is that, until you get your head around how it works, it's *really hard* to figure out.

I'm not keen on pack, FWIW. 

If I find time I'll post an illustration later...

--
Ian
From my Fairphone FP3

Ian MacArthur

unread,
Nov 30, 2021, 11:35:38 AM11/30/21
to fltk.general
And here's the aforementioned illustration: Compiled and tested with  "fltk-config --compile layout.cxx", worked OK.

*Why* it works is left as an exercise for the reader, as it's too hard to explain...
----------------------------------

#include <FL/Fl.H>
#include <FL/Fl_Group.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Box.H>
#include <FL/Fl_Button.H>

static Fl_Double_Window *main_win = (Fl_Double_Window *)0;

static void cb_quit_bt (Fl_Button *, void *)
{
    main_win->hide();
}

#define WWD 690
#define BWW 64
int main (int argc, char **argv)
{
    main_win = new Fl_Double_Window (WWD, 360, "Test Window");
    main_win->begin();

    Fl_Group *g1 = new Fl_Group (0, 0, WWD, 300);
    g1->begin();
    //g1->box(FL_BORDER_BOX);

    Fl_Group *g2 = new Fl_Group (0, 25, WWD, 27);
    g2->begin();
    //g2->box(FL_BORDER_BOX);

    Fl_Group *g2a = new Fl_Group (0, 25, 230, 27);
    g2a->begin();
    //g2a->box(FL_BORDER_BOX);

    Fl_Button *b1 = new Fl_Button (5, 25, BWW, 23, "B1");
    Fl_Button *b2 = new Fl_Button (70, 25, BWW, 23, "B2");
    Fl_Box *sp2 = new Fl_Box (135, 25, 1, 1);
    //sp2->box(FL_BORDER_BOX);

    g2a->end();
    g2a->resizable(sp2);

    Fl_Group *g3 = new Fl_Group (276, 25, WWD - 276, 27);
    g3->begin();
    //g3->box(FL_BORDER_BOX);
    Fl_Button *b3 = new Fl_Button (276, 25, BWW, 23, "B3");
    Fl_Button *b4 = new Fl_Button (340, 25, BWW, 23, "B4");
    Fl_Box *sp3 = new Fl_Box (404, 25, 1, 1);
    //sp3->box(FL_BORDER_BOX);

    Fl_Group *g4 = new Fl_Group (WWD - BWW - BWW - 10, 25, BWW + BWW + 10, 27);
    g4->begin();
    //g4->box(FL_BORDER_BOX);
    Fl_Box *sp4 = new Fl_Box (WWD - BWW - BWW - 10, 25, 1, 1);
    //sp4->box(FL_BORDER_BOX);
    Fl_Button *b5 = new Fl_Button (WWD - BWW - BWW - 5, 25, BWW, 23, "B5");
    Fl_Button *b6 = new Fl_Button (WWD - BWW - 5, 25, BWW, 23, "B6");
    g4->end();
    g4->resizable(sp4);

    g3->end();
    g3->resizable(sp3);

    g2->end();

    Fl_Box *sp1 = new Fl_Box (1, 52, WWD - 2, 248);
    //sp1->box(FL_BORDER_BOX);

    g1->end();
    g1->resizable(sp1);

    Fl_Button *quit_bt = new Fl_Button (WWD - BWW - 5, 322, BWW, 23, "Quit");
    quit_bt->callback ((Fl_Callback *)cb_quit_bt);

    main_win->end();
    main_win->resizable (g1);

    main_win->show (argc, argv);
    return Fl::run();
}

// end of file //

 

Mark

unread,
Nov 30, 2021, 11:37:13 AM11/30/21
to fltk.general
Thanks again for helpful replies. It seems the experimental Fl_Flow has just been ported to Rust by the person who did the bindings: https://github.com/MoAlyousef/fltk-flow so I'll start with that.

Greg Ercolano

unread,
Nov 30, 2021, 1:08:16 PM11/30/21
to fltkg...@googlegroups.com

On 11/30/21 7:05 AM, Albrecht Schlosser wrote:

On 11/30/21 2:46 PM 'Mark' via fltk.general wrote:
I want to have a row of buttons like this:
[New] [Options] ...gap... [About] [Help] ...gap... [Quit]
With standard FLTK (1.4, git, as of today) I'd derive my own container widget from Fl_Group and override the resize() method.


However, I'm working on a new Fl_Grid widget that can do easily what you want to achieve. This is intended to be in FLTK 1.4.0 when released, hopefully early in the next year (Jan, Feb, Mar?).

    Yes, this is a perfect example of where the new grid layout widget would be
    useful.

    While it /can/ be done using the default fltk Fl_Group and resizable() behavior
    (as Ian shows), it can be very not pretty and unclear.

    And agreeing with Albrecht that, in the absence of Fl_Grid or such layout widget,
    the next best way is derive a custom class from Fl_Group and override resize().
    An example of that approach is attached.

gap.cxx
gap.png

duncan

unread,
Nov 30, 2021, 1:13:25 PM11/30/21
to fltk.general
I want to have a row of buttons like this:

[New] [Options] ...gap... [About] [Help] ...gap... [Quit]

Where the first two are aligned to the left of the parent window, the middle two are in the middle of the row and the last one is on the right. And of course I want them to keep these relative positions when the window is resized.
 
And here's the aforementioned illustration: Compiled and tested with  "fltk-config --compile layout.cxx", worked OK.

*Why* it works is left as an exercise for the reader, as it's too hard to explain...

Cough! There's a page about how resizing works in the 1.4.x documentation:

D.

Mark

unread,
Dec 1, 2021, 5:57:43 AM12/1/21
to fltk.general
Thank you for all your suggestions.
I reread the FLTK docs on layouts and tried to use its advice, but was still defeated.
I did succeed in the end though, no thanks to the docs! I used a flex layout. I set each button to a fixed size and put a tiny frame in each of the two gaps. The flex layout automatically gave all spare space to these frames (and seems to do so equally), so I got the exact layout I wanted.

Ian MacArthur

unread,
Dec 1, 2021, 7:22:06 AM12/1/21
to fltk.general
On Wednesday, 1 December 2021 at 10:57:43 UTC Mark wrote:
Thank you for all your suggestions.
I reread the FLTK docs on layouts and tried to use its advice, but was still defeated.
I did succeed in the end though, no thanks to the docs! I used a flex layout. I set each button to a fixed size and put a tiny frame in each of the two gaps. The flex layout automatically gave all spare space to these frames (and seems to do so equally), so I got the exact layout I wanted.

OK - glad you got something sorted out.
The default fltk resizable system is actually very neat and powerful - but it is also true that most folks find it counterintuitive until they get to grips with it...


And, as an unrelated aside: you say "tiny frame" and "these frames" in your post - and I take that to indicate you are using "frame" here in the sense that Mo used in the Rust port...?

If so, you should probably be aware that in (C++) fltk, "frame" and "box" are distinct things (though both refer to how widgets are rendered) and that I think Mo used "frame" in Rust to refer to what would be called "box" in C++  (I think he had a problem with "box" potentially colliding with Rust language features or something...?) and that in the past this has led to some "confusion" here with Rust users talking about "frames" and... you get the idea... Worth being aware of that, just in case!



Mark

unread,
Dec 2, 2021, 7:15:51 AM12/2/21
to fltk.general
Yes, there's no box in fltk-rs, just an fltk::frame::Frame. Box is actually a kind of pointer in rust.
Reply all
Reply to author
Forward
0 new messages