Wow, this looks neat.
Scroll down on the project's main github main page and you're
sure to understand how it works right away.
Nice use of ascii art for positioning hints.. love it.
Didn't look at the code, but if it's a single .H file,
I can guess it's "light" and simple.. Nice!
Assuming the other devs agree (we'll give it a look over),
is it OK to add it to FLTK itself and its LGPL license?
I have had a little bit of time to port a layout manager we use for an internal UI system to FLTK. It may seem a little weird to use at first but it allows for extremely quick layout and prototyping. It was originally designed to quickly hack together UIs for ever-changing scientific research tools. However it started to become a preferred layout system for everything because it was quick easy and maintainable.So please do give it a go if you have time. Or at the very least have a skim through the tutorial on the main project page to see if it may be useful to you.
However, I notice that the code uses exceptions and templates, which might be a problem forinclusion within the core of FLTK because the CMP currently prohibits their use, but there'sprobably nothing to stop Fl_Flow being offered as part of an add-on system. FLTK++ perhaps?
Hello,> Assuming the other devs agree (we'll give it a look over),
> is it OK to add it to FLTK itself and its LGPL license?> However, I notice that the code uses exceptions and templates,Oh, I didn't expect there to perhaps be interest to add it into FLTK itself. Otherwise i probably would have avoided the templates. Again, I used them to make it as easy as possible for others to drop into a project. But if Fl_Flow is added to FLTK anyway then this avoids that problem entirely.
To be fair, the nice thing about this layout system is that it isn't too complex or large to write. If people do decide that they would like to add it into FLTK itself, I can happily de-templatize it. I do use std::string, std::exception and std::vector but these can also be replaced if necessary. Their use is fairly minor.
I haven't added a license yet. Depending on what people want to do with it I am happy with GPL, BSD, etc.
From: Ian MacArthur
Sent: 29 October 2021 11:28
To: fltk.general
Subject: [fltk.general] Re: [Fl_Flow] A new layout manager for FLTK
As a matter of interest what is the issue with exceptions?
Regards Phil.
Removing STL and templates is fine. Actually the internal version of this system was originally written entirely in ANSI C89. I do have a very (1 year) old version which is still public. Perhaps people might find the uncanny similarity interesting (especially the adapted tutorial). The entire C project was meant to remain open-source but it became a bit butchered to work on an entirely different widget system.
[ OLD C VERSION ]
https://osen.github.io/flow.html <-- C-style tutorial
https://github.com/osen/iffe/tree/main/src/iffe <-- Old codebase
Had I known there was a potential for inclusion with FLTK I would have brushed up on the coding conventions and stuck to them. But either way, if people have a play and think that they will still be interested, let me know and I can spend a bit of time making it more suitable for integration.
--
You received this message because you are subscribed to the Google Groups "fltk.general" group.
To unsubscribe from this group and stop receiving emails from it, send an email to fltkgeneral...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/fltkgeneral/60dcdaf6-af88-785b-bbae-1ebcdb71c2eb%40online.de.
--
You received this message because you are subscribed to the Google Groups "fltk.general" group.
To unsubscribe from this group and stop receiving emails from it, send an email to fltkgeneral...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/fltkgeneral/ef599b5c-d09d-35af-379f-9e60b874f6a8%40online.de.
On 10/29/21 7:27 PM Karsten Pedersen wrote:
(2) Very happy to. Though do I need to look up at how FLTK deals with operator new() throwing exceptions on OOM situations.
We don't. ;-)
For handling new in my daemon application, I used a hook (I
forget the details)
to hook into both new and malloc() so that out of memory
conditions basically
retry with a sleep until it succeeds, preventing a crash due
to the machine being
overloaded by, presumably, some other application that will
eventually be killed
by the OOM killer or a user.
I don't ever try to handle out of memory conditions in the
app; the best thing IMHO
is to wait a little and try again so that a memory allocation
never fails.
(3) std::string is easy, I barely use it. I could just use standard C-Style strings. I will have a look through FLTK and see what you guys use for containers. If not I can put together some C-style linked list, etc.
We don't use any containers yet (officially) although there are some (inofficial, i.e. not public) containers used in some implementations, for instance Fl_Table::IntVector. Picking existing container types, putting them in classes etc., making them kinda "protected" or "public" is on my todo (ehm, wish) list though. With "protected" I mean in this context that they could be inside the library code base but not in the public header files. Public would mean that they'd be in the FL/ directory for public usage.
Bill wrote in his comment "I don't have any problem with using std::vector, it was not used back in the day because it used much more memory and was slower than naive C implementations, but this is not true any more." We *might* reconsider using std::vector in the future which would simplify some, particularly new code.
OTOH the strings used could likely be simple char* arrays as Bill mentioned as well.
(5) OK, I will push to my repo on GitHub an LGPL LICENSE file. I can perhaps grab one with the exceptions in it from the FLTK project repo.
Great.
One thing I would like to see is support for "outside" labels to produce nice columns. If a whole bunch of widgets with outside-left labels are pushed to the left, they should instead be positioned so the label fits, and the maximum size of all the labels is used for this.
It would be nice to compute a minimum size to fix the layout issue with #9 above.
As far as I can tell, FLTK widgets don't have a minimum size? I.e Fl_Buttons, etc. Potentially if they all had a default constructor that set this size would make it even more convenient for Fl_Flow because it wouldn't need to be set in i.e an initializer list.
Question: Have you ever seen that happen?
can not be honoured by the MMU at point of use, you can get tricky (and hard to debug) faults “elsewhere” in the program at runtime.
I think what Bill meant was the *maximum* (not minimum) size of all outside labels (and I may add: in the same "column"). That would mean that you reserve space for all labels at the left side of the Fl_Flow widget to place the outside labels and align the widgets right of the labels in one "column".
I was referring to this line earlier from Bill:> It would be nice to compute a minimum size to fix the layout issue with #9 above.I think perhaps this was to address your (9), widgets sticking to bottom right if the window is too small. Perhaps if we could calculate the minimum size we could make the Fl_Flow widget from its contained widgets, we could do something with that. Perhaps we could even compute the minimum window size from that.
Obviously one complexity arises because depending on one dimension the window may not collide in the other dimension. You could end up with a smaller window, but one that is shaped in a way that no widgets collide.
Commit 40e23c163584f is the one with all the necessary modifications to
remove Fl_Widget_Tracker. Feel free to use my changes in your process to
make it more FLTK compatible. TIA.
rom: Ian MacArthur
Sent: 29 October 2021 21:48
To: Fltk General
Subject: OT: thread drift Re: [fltk.general] [Fl_Flow] A new layout managerfor FLTK
Thanks Ian,
Makes sense. As not a professional programmer, I have acquired a few bad habits.
Phil.
On 10/30/21 12:26 AM Karsten Pedersen wrote:
On Friday, October 29, 2021 at 9:58:13 PM UTC Albrecht Schlosser wrote:
Commit 40e23c163584f is the one with all the necessary modifications to
remove Fl_Widget_Tracker. Feel free to use my changes in your process to
make it more FLTK compatible. TIA.
Makes sense. As not a professional programmer, I have acquired a few bad habits.
--
You received this message because you are subscribed to the Google Groups "fltk.general" group.
To unsubscribe from this group and stop receiving emails from it, send an email to fltkgeneral...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/fltkgeneral/FEFAB9CA-FC59-4C94-90F8-3A48B7F63C0F%40gmail.com.
However an FLTK program must be able to call a library that uses exceptions (at least from user-defined callback functions), and FLTK must be usable by a program that is using exceptions. I think this is true in modern compilers no matter how FLTK itself is compiled.
Some suggs:
On 11/1/21 10:53 AM, Albrecht Schlosser wrote:
It looks simple in the tutorial [..] the results are great.
Just an FYI, I have now separated out the header and .cxx in my branch here:
One thing that came up due to new code and the removal of Fl_Widget_Tracker is here:
This comparison might be done on a dangling pointer (to a Widget that had just been removed / deleted). The comparison itself isn't unsafe as such and the code after it doesn't access the invalid memory. Perhaps the worst that could happen is a new widget being added that happens to reclaim the same pointer so gets set an incorrect size because it reuses the original set by the deleted widget before it.
I am tempted to call prepare() at the beginning of this function to wipe obsolete pointers but that would be needlessly costly at this point. It is something to keep note of.
I see std::string is already replaced which is good. My next task will be to replace the std::vector<T> with a linked list for both Instructions and States.
Finally, you will see in my original repository here, I have added the FLTK LGPL license file that I am happy to release my code under:
I am not massively keen on that resize_callback stuff. Purely because the sample test which utilizes it is looking too complex for what I would expect a developer to implement each time.
I am thinking maybe something instead like:
m_flow.rule(button, "^<=>[33%]");
could be a better choice to "move up, then left then expand right to 33%" of the remaining screen space.It would require a more substantial interpreter but *should* allow for nice dynamic column resizing.
but "reading" other person's code is a little different.
It looks simple in the tutorial but it can be pretty complex even in
such a "small" login window.
Please see my other message with a potential fix.
If we're using your code I suggest to add the official FLTK boiler plate with a copyright statement of your choice (or, as you like, just the normal "Bill Spitzak and others" copyright.
I was also looking for a way to center, say, two or three objects in one row such that the space left and right of the objects is equal. Generally maybe an instuction to center all objects in one "row" after filing the available space.
One of your demos shows how the text input widget can be expanded to take the full space left above the (one) button at the bottom. What if I want to add more than one row of buttons at the bottom? Is there a way to achieve this while still expanding the text input field above to full size?
I think all or some of these questions can be resolved by nesting Fl_Flow widgets but maybe there's a better way?
Please don't understand me wrong, this is not to criticize your work which is really great. I'm asking these questions as a "normal user", anticipating that users would have such questions too.
That said, there's one more technical aspect: the Fl_Flow widget should be a "class" rather than a struct, as all other FLTK widgets are. The helper structs can IMHO remain structs or can become classes as well, as it fits.
Regarding Greg's change, moving the helper structs into the class: +1. But I'm not sure if some of the structs and/or variables would need to be protected just in case users want to derive their own classes.
One last suggestion for now: I see that you are parsing (decoding) the rules and combining characters, e.g. "=>" into one Fl_Instruction.
On Monday, November 1, 2021 at 6:51:02 PM UTC Albrecht Schlosser wrote:
but "reading" other person's code is a little different.
It looks simple in the tutorial but it can be pretty complex even in
such a "small" login window.
Yeah, I do understand this. I look at some of my test forms and do get a little confused. What I find helps is to just follow the instructions through from the start and try to visualize it. I think some comments next to each one can help, even just the names of the instructions, "up, left, etc". Sometimes, even though you can get away without, nesting Fl_Flow containers can be preferable.
Please see my other message with a potential fix.
OK, I am happy with this fix and have applied it. It is indeed more efficient than calling prepare(). I also looked at the code behind Fl_Widget_Tracker and can see that scans through a list of children.
Possibly a future solution will be something like std::weak_ptr<T> which stores a reference count and only when the last reference (strong *and* weak) goes out, does it clean up. That way its speed is mostly O(1) rather than O(n). It will also solve the issue of address reuse.
If we're using your code I suggest to add the official FLTK boiler plate with a copyright statement of your choice (or, as you like, just the normal "Bill Spitzak and others" copyright.
OK, I have added my name "and others" because a few of us here have worked on Fl_Flow so far in the last couple of days.
I was also looking for a way to center, say, two or three objects in one row such that the space left and right of the objects is equal. Generally maybe an instuction to center all objects in one "row" after filing the available space.
Indeed, you may have spotted my login example only has one text box (username) rather than password, etc. Basically, I couldn't yet think of a way to do it "easily" without nesting. So I agree that some sort of solution here could be good. Of course you could position on in the center (or [25%] if we implement that) and then simply stack the others below it. However a way to group a bunch of them conveniently centered could indeed be nice and reduce typing and complexity.
One of your demos shows how the text input widget can be expanded to take the full space left above the (one) button at the bottom. What if I want to add more than one row of buttons at the bottom? Is there a way to achieve this while still expanding the text input field above to full size?
If you add a new button, move it up. It will hit the text input and stop. Then give it a down instruction and it will hit the top of the original button. This will then be the start of your second row. Move the button left and repeat for the next one. This could be dome in a little more of a controlled manner with a (hidden?) separator. Or of course a nested Fl_Flow.
I think all or some of these questions can be resolved by nesting Fl_Flow widgets but maybe there's a better way?
Please don't understand me wrong, this is not to criticize your work which is really great. I'm asking these questions as a "normal user", anticipating that users would have such questions too.
Yes, I absolutely understand. This whole layout system is fairly experimental and evolving so I am very happy to hear your insights as we explore it and including any potential issues. What I do want to avoid is someone coming up to maintain a GUI program, only to be greeted with:
m_flow.rule(m_content, "<^/>^/>/^<v=^><=>^v</>/>/^"); // Position the content
Whilst setting the destructor virtual,
I was thinking to myself what inheriting from this widget would be like. Personally I feel it would be very difficult as it stands because I would assume the user is trying to add new instructions (or they would simply inherit from Fl_Group instead, in which case they would really want to tap into the process() function itself, rather than override something like resize(), etc.
One last suggestion for now: I see that you are parsing (decoding) the rules and combining characters, e.g. "=>" into one Fl_Instruction.
True. I think there certainly is room for optimising this part. In particular I was thinking bitmasks such as:
if (instruction & EXPAND) { ... }
I am also going to start looking at adding some doxygen comments too (I will clone the syntax used in other units).
Indeed, you may have spotted my login example only has one text box (username) rather than password, etc. Basically, I couldn't yet think of a way to do it "easily" without nesting. So I agree that some sort of solution here could be good. Of course you could position on in the center (or [25%] if we implement that) and then simply stack the others below it. However a way to group a bunch of them conveniently centered could indeed be nice and reduce typing and complexity.
On 11/1/21 11:08 PM Karsten Pedersen wrote:
Indeed, you may have spotted my login example only has one text box (username) rather than password, etc. Basically, I couldn't yet think of a way to do it "easily" without nesting. So I agree that some sort of solution here could be good. Of course you could position on in the center (or [25%] if we implement that) and then simply stack the others below it. However a way to group a bunch of them conveniently centered could indeed be nice and reduce typing and complexity.
I'm attaching my modified version of the flow_login.cxx example program with two text boxes (username and password). The boxes are not really centered but appear in the right place. I added comments to explain what is going on.
Yes it would, but we don't use such "modern" stuff. ;-)
I see. But such instructions tend to be "write-only": once you've written it and read it again you don't know what's going on and why you did that.
Layout (Fl_Pack, Fl_Flow, Fl_Flex (?), Fl_Grid (?) and others) and resizing with FLTK standard means can all be grouped together in one chapter. But that's something we can attack later.
... once you are done and you read it back, it makes almost zero sense!
Layout (Fl_Pack, Fl_Flow, Fl_Flex (?), Fl_Grid (?) and others) and resizing with FLTK standard means can all be grouped together in one chapter. But that's something we can attack later.
Yes absolutely. It will be really nice to have information on all the different layout systems. I have seen similar pages for Motif, Qt and javax.swing and it provides good insight as to where one might be more suitable than another. Ultimately I would also like to provide a tutorial program (test or sample) that takes the user through the same tutorial but as part of an interactive GUI program.
As an aside, I have committed your changes to flow_login.cxx.
With the comments it is much more understandable. We are lucky in this specific example that the centered panel never changes size, so we can use a hard coded value of '100' for the topPad.
However if we did want this to resize at some point, then we might need to look at adding percentile instructions like:
center.rule(topPad, "=^[10%]^=<"); // Resize to 10% of height, reserve space above input boxes
I proposed a “fluent” interface to Fl_Flow, and Karsten has graciously merged it:
https://github.com/osen/Fl_Flow/tree/main/src/fluent
The idea is that instead of using ASCII characters like this
flow.rule(sep, "=<^");
You would write this
flow(sep).left().expand()
.up();
Thanks,
Jose
On Wednesday, November 23, 2022 at 8:41:13 AM UTC-8 may64…@gmail.com wrote:
The interface is really nice.A nit I had while trying things out. Things didn't work initially since the headers lacked include guards and lacked includes of the other relevant headers (Fl_Helper, Fl_Exception ...etc).Looking at the makefile, the include guards and proper includes seem to be added there:```cat $(INCLUDES) >> include/FL/Fl_Flow.H```I prefer for header-only libs that they be directly usable without having to go through a make step.
Originally include/FL/Fl_Flow.H
was checked in, but that file is generated from the .h
files in src/Fl_Flow
, as you point out.There’s also a Fl_Flow.h
(note the capitalization) in that folder. This caused me lots of confusion while I was developing this feature. I kept making changes in Fl_Flow.H
only to have them disappear the next time I ran make
. IMHO, generated files should never be checked in, but ultimately this is up to Karsten, of course. I was somewhat surprised that he accepted that change without comment.
Originally
include/FL/Fl_Flow.H
was checked in, but that file is generated from the.h
files insrc/Fl_Flow
, as you point out.There’s also aFl_Flow.h
(note the capitalization) in that folder. This caused me lots of confusion while I was developing this feature. I kept making changes inFl_Flow.H
only to have them disappear the next time I ranmake
. IMHO, generated files should never be checked in, but ultimately this is up to Karsten, of course. I was somewhat surprised that he accepted that change without comment.
On 11/26/22 09:05, Jose Q wrote:
Sorry for the janky quoting. It's the only way I've found to not top post when using the Web interface. What's a good client for navigating these groups?
Sure, but "different folders" is not always a robust solution - if the include path is such that the compiler can/will search both folders, you still can get collisions, or weird behaviour where it depends what order the include folders are searched and so on... Which can be quite confusing to debug at times!
So, I’m a big fan of keeping the names unique, basically (you may have spotted that...)