GWEN UI Allegro5 port
billyquith

I have ported the GWEN UI to Allegro 5 :). I'm not an expert at unicode so I had a little trouble with the font rendering. It seems to work, but I'm not sure if it is correct. ??? Not quite sure how to convert std::wstring to ALLEGRO_USTR.

Code is here. The is an input header and the other two are the renderer.

http://code.google.com/p/gwen/issues/detail?id=56

GWEN is a very nice UI and it would be nice if it fully worked with Allegro 5:

http://code.google.com/p/gwen/

Perhaps if you know how to fix it you could post the files to the GWEN link above.

Cheers. :)

Trent Gamblin

That looks good. Nice job. Not sure about std::wstring but Allegro uses utf8 so AFAIK you can use std::string.

Elias

Not quite sure how to convert std::wstring to ALLEGRO_USTR.

Should be simple, something like (untested):

ALLEGRO_USTR *wstring_to_ustr(std::wstring w) {
    ALLEGRO_USTR *u = al_ustr_new("");
    for (int i = 0; i < w.size(); i++) {
        wchar_t wc = w[i];
        al_ustr_append_chr(u, wc);
    }
    return u;
}

Then make sure to free the string later with al_ustr_free.

If looping through all characters is too slow, you could also simply assume that wstring.cstr() is UTF16 under Windows:

ALLEGRO_USTR *wstring_to_ustr(std::wstring w) {
#ifdef ALLEGRO_WINDOWS
    return al_ustr_new_from_utf16(w.c_str());
#else
    return al_ustr_new(w.c_str());
#endif
}

However that's probably a bit hackish as it depends on the exact windows version / exact OS version.

Quote:

Allegro has not right alt?

It's called ALTGR because that's what it's called in England. We probably should add a #define.

weapon_S

Looks good. I don't have time to try it out now. Does it compile and build? An example Allegro program would be super.

billyquith
Elias said:

It's called ALTGR because that's what it's called in England. We probably should add a #define.

Right, thanks, will try that. I have Mac keyboard with "alt" on the right. I noticed a Windows/PC keyboard has "Alt Gr" today.

Neil Walker

I can't see any kind of documentation or api reference?

axilmar

The GWEN guy put a lot of work in it, and the API seems good. However, it has a profound lack of documentation, and I also think it misses layout management (although I am not sure - I saw a 'layout' method somewhere).

billyquith
axilmar said:

The GWEN guy put a lot of work in it, and the API seems good. However, it has a profound lack of documentation, and I also think it misses layout management (although I am not sure - I saw a 'layout' method somewhere).

That is pretty much my take on it: both docs and layout. If you have used other UI APIs then it isn't that hard to tackle. But its the annoying-ness of having to figure out which flags do what and what the difference between a margin and padding is, etc.

Perhaps reply to this issue if you would like to see docs: http://code.google.com/p/gwen/issues/detail?id=64

If you look in Gwen::Align there are some functions for doing alignment. I've added a few more myself. When I'm happier I'll add them to the GWEN issues list. I would also like to see horizontal and vertical spacers, like wx. They are very useful.

Edgar Reynaldo

As someone who has their own fairly complete GUI library (minus docs and a few widgets), I have really never understood what a layout manager would actually do. Is it like an HTML renderer? Does it position everything according to a set of rules? How could you possibly make it intelligent enough to always reposition everything the way the user wanted it to? In my library, all the positioning and resizing is done by the user themself, because I haven't thought of a good way to do it for them yet.

jmasterx

@Edgar

Have you looked at Java's explanations?
http://download.oracle.com/javase/tutorial/uiswing/layout/visual.html

I find the most useful ones are FlowLayout and BorderLayout. Surprisingly, many applications happen to have 2 borders that are fixed on width, 2 fixed on height and a stretchable center area.

Oscar Giner

Edgar: look at Qt's layout system. It's pretty good. Very easy and simple for not very complex layouts, but very powerful to allow very complex layouts. I still haven't come with a layout design that it can't handle. You can even inherit your own layout class in case you want something very specific and implement the layout yourself (for example, you may want some kind of multi-line layout, where widgets are positioned aligned horizontally, but if there's not enough space to place them all in a single line, it automatically creates a new line and continues from there. One of Qt's examples is just an implementation of this layout).

Matthew Leverton

How could you possibly make it intelligent enough to always reposition everything the way the user wanted it to? In my library, all the positioning and resizing is done by the user themself, because I haven't thought of a good way to do it for them yet.

I had my doubts as well, but after implementing just two different layouts (vertical and horizontal boxes), I was impressed at how simple it made creating dialogs.

I was going to write up something that explained it, but it's hard to do in a few words. But basically if your layout manager has cells, and each cell can contain other layout managers, you can have quite complex layouts with only two different layouts: vertical/horizontal boxes.

The two concepts I introduced to solve sizing issues were:

  • Changing algui_resize(widget, w, h) to indicate a requested size (as opposed to actual size). Added algui_set_constraints(widget, min_w, min_h, max_w, max_h).

  • Give each cell the opportunity to request a "stretch factor" which is how unused space is divvied up.

So the sizing is determined by querying each widget, asking for their requested dimensions. Then the extra space is allocated based on the stretch factors, which are just ratios.

Trent Gamblin

I have basically the same thing as Matthew in my GUI except I put them in the same widget. I even have the scale factors. I've build a moderately complex level editor with just that one layout widget which includes many of the standard elements in other guis (lists, menus, sliders, buttons, scrollpanes etc).

Edgar Reynaldo

Thanks for the suggestions. Since my GUI is based on A4, and the windows aren't resizable, I don't think I'll really need a layout manager yet, but you've given me some ideas I can work with, so thanks. :)

ImLeftFooted

Apple has these auto resizing rules.
{"name":"Picture%202011-09-24%20at%201.57.10%20PM.png","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/d\/b\/db254dc1877b8491009da699f35175c7.png","w":252,"h":99,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/d\/b\/db254dc1877b8491009da699f35175c7"}Picture%202011-09-24%20at%201.57.10%20PM.png

The two center lines say whether they'll stretch vertically and horizontally. The four outer lines are kind of like "stick to this wall". So the first example sticks to left and top and does no resizing. Here is a widget that would be fullscreen and resize with the window:
{"name":"Picture%202011-09-24%20at%201.58.35%20PM.png","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/e\/2\/e291d8980fecf6fea037af5217f45c4a.png","w":253,"h":89,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/e\/2\/e291d8980fecf6fea037af5217f45c4a"}Picture%202011-09-24%20at%201.58.35%20PM.png

This would cling to the bottom (and left):
{"name":"Picture%202011-09-24%20at%201.59.49%20PM.png","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/d\/9\/d96e156019c81228799d399d6c510594.png","w":254,"h":89,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/d\/9\/d96e156019c81228799d399d6c510594"}Picture%202011-09-24%20at%201.59.49%20PM.png

In addition they let you choose from some sizing logic options:
{"name":"Picture%202011-09-24%20at%202.00.52%20PM.png","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/7\/a\/7a40de73629237b15472f8e9ed41a38b.png","w":259,"h":244,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/7\/a\/7a40de73629237b15472f8e9ed41a38b"}Picture%202011-09-24%20at%202.00.52%20PM.png

With those these two tools you can do most things.

axilmar

As someone who has their own fairly complete GUI library (minus docs and a few widgets), I have really never understood what a layout manager would actually do. Is it like an HTML renderer? Does it position everything according to a set of rules? How could you possibly make it intelligent enough to always reposition everything the way the user wanted it to? In my library, all the positioning and resizing is done by the user themself, because I haven't thought of a good way to do it for them yet.

Layout is fairly easy to do in a GUI. It's a 2-step algorithm:

  • 1st step: let each widget take its optimum size, based on its contents. Do this first for children widgets, then for parent widgets, in order to allow parents to wrap themselves around their children.


  • 2nd step: let each widget position its contents, based on its size. Do this first for parent widgets, then for children, so as that parents define where children are positioned.

The layout algorithm has to be called in the following cases:

  • when a widget is inserted in another widget.

  • when a widget is removed from another widget.

  • when a widget is resized.

  • when a widget is hidden or shown.

  • when a visual property of a widget that affects its size is modified.

I can tell you more, if you're interested. Suffice to say that using a GUI library that has layout management is a lot better than one without.

Edgar Reynaldo

Apple has these auto resizing rules.

The two center lines say whether they'll stretch vertically and horizontally. The four outer lines are kind of like "stick to this wall". So the first example sticks to left and top and does no resizing. Here is a widget that would be fullscreen and resize with the window:

I see how that works with a single widget, but how would those rules work with multiple widgets? Would that technique be combined with use of one layout cell per widget? So the cell would take up at least as much extra space as the fixed width margins as shown, and as much extra space was available for the floating margins as shown?

And as far as positioning and resizing goes with a layout manager, the positions would never be specified, but only set by the layout manager? And the sizes would be determined by a recommended size instead of having the user set the sizes explicitly?

Axilmar said:

1st step: let each widget take its optimum size, based on its contents. Do this first for children widgets, then for parent widgets, in order to allow parents to wrap themselves around their children.

I don't really understand this step. My widgets have virtual functions that return the absolute minimum width and height that they can occupy, but how could you ever determine what an optimum size would be? Would they follow an 'expand as space allows' rule like in Dustin's example of floating margins? Isn't that something the layout manager would have to determine, and not the widget itself?

J-Gamer

And as far as positioning and resizing goes with a layout manager, the positions would never be specified, but only set by the layout manager? And the sizes would be determined by a recommended size instead of having the user set the sizes explicitly?

^This. I've been busy making a scripted layout engine, and everything on the screen needs a Position, which is user defined in percentages of the parent.

Matthew Leverton

I cannot speak for axilmar, but my algui_resize() sets the optimal size. The minimum and maximum sizes are set by another function.

Say you have a horizontal layout with three cells. The third cell contains another horizontal layout with two cells. The outer layout is 90 actual pixels wide. Its children widgets' optimal widths are represented by the numbers.

| 10 | 20 | (10, 20) |

So from that parent layout's POV, you end up with optimal widths of:

| 10 | 20 | 30 |

That's a total of 60 pixels, with 30 left over. Let's say each cell has the same stretch factor of 1. Each cell then gets an extra 10 pixels, so the cells are:

| 20 | 30 | 40 |

The layout is happy... it equals 90.

Now the child layout in the third cell looks like:

| 10 | 20 |

but since it has 40 pixels to play with, it divides the 10 extra pixels:

| 15 | 25 |

The big picture is:

| 20 | 30 | (15, 25) |

What I do then is check each widget's constraints. Maybe that first widget has a maximum width of 10. Since it has 20 pixels allocated, it then has 10 pixels of padding/margin. You can tell the cell to align left, right, or center in that case.

My approach isn't perfect because you could end up with a case where one widget is smaller than its minimum size at the same time there's another widget that is larger than its optimal size. A smarter algorithm could take some space away from the larger widget to accommodate the smaller one.

That could be done with another pass, but I didn't care enough to do anything about it because it really isn't an issue in cases that aren't contrived. All you have to do is make sure your container's minimum size is sufficient to display its children.

Edgar Reynaldo

I just don't understand the idea of an optimal size. Do you mean a user specified desired size? How else would the widget know how to set it's width between it's minimum and maximum width?

Matthew Leverton

Do you mean a user specified desired size?

In practice, yes. It's the size the widget would be in the absence of a layout manager because the user explicitly requested it. (I do have a concept of "default" widget size. For instance, a button may default to being as wide as its text caption. But the programmer's request to resize the widget overrides that.)

The layout manager simply treats that size as a starting point to determine how much free space is left over. It then uses the cell's stretch factors to determine how to divide that left over space up.

Again, this is just my approach. There are many ways to do this... because generally you can trust the programmer to not create unrealistic edge cases.

axilmar

I don't really understand this step. My widgets have virtual functions that return the absolute minimum width and height that they can occupy, but how could you ever determine what an optimum size would be? Would they follow an 'expand as space allows' rule like in Dustin's example of floating margins? Isn't that something the layout manager would have to determine, and not the widget itself?

It's very easy: the optimum size is the smaller size a widget can occupy without affecting the widget's operation.

For example, in case of a button, the button's text and/or bitmap should be visible, as well as the margin.

In case of a check box, the check and the text should be visible.

In case of a text box, the minimum number of characters for the specified font should be visible.

In case of a list box, if there are few entries, then they all should be visible; if there are many entries, the first few should be visible etc.

In case of a dialog, the dialog's controls should be visible.

So, in this step, each widget lets each children specify their minimum size, then the parent specifies its minimum size. In any case, each widget specifies its size based on its contents (children widgets or text/bitmap/other).

Edgar Reynaldo
axilmar said:

It's very easy: the optimum size is the smaller size a widget can occupy without affecting the widget's operation.

That's the minimum size, not the 'optimum' size. An 'optimum' size can only be input by the user, not determined by the widget itself. Except in the case of widgets that have scrollable areas, and in that case I guess the 'optimum' size could be considered to be the one that shows all the contents without the aid of a scrollbar.

Oscar Giner

No, the minimum size can be less. While the optimum size of a button is what aximlar said, its minimum size will be much smaller (but the text won't fit inside). axilmar definition is probably not the best, since in this case for example the button is still usable with a size smaller that its optimum (but usability is reduced since the user can't fully read the button's contents).

Optimum size is determined by the widget, not the user. The widget knows the size of the button border in a given skin/OS, and the text size.

Another example of optimum size, is the width of an line input widget with a set maximum of characters. In this case the optimum size would be the one where no matter what the user writes in it, it fits without the need for scrolling.

This optimum size is dynamic, and can change while the app is running (button caption changes, for example). Min and max sizes are usually static (unless the user explicitly changes them).

Edgar Reynaldo

A button that doesn't clearly display it's text is not really a usable button. How would you know what it does? Press the button, and hope for the best? I don't strictly enforce a minimum size for my text buttons, but I probably should.

I'll agree that scrollable widgets might have a notion of an optimum size, but not all widgets could ever hope to know what their 'optimum' size is. A slider would not have any idea what it's optimum size would be, only what it's minimum size would be. Same goes for a scrollbar. What about a camera widget? What about an icon button? If it stretches it's contents, what should it's optimum size be? What about a tab? Would you want a tab that didn't fully show it's text? That's another case of a minimum size, and not an optimum size. All of these 'optimums' would have to be specified by the user.

Matthew Leverton

ahh, so many it's=>its failures

I think there's not really much here to argue. That is, I don't think any of you are actually disagreeing on any high level concepts... Practically speaking, the widget's true minimal drawing size is irrelevant to the programmer.

Say I have a container with 100 pixels of space. I want to draw a button in there that I assign a minimal size of 150 pixels. The actual minimal size is, say, 30 pixels. So technically the button could fit in that 100 pixels of space.

However, I've declared the minimum size to be 150 pixels. Thus the button should be drawn internally at 150 pixels but cropped to 100 when it goes into the parent container. It's my own fault if that wasn't my intention.

If I wanted the button to fill the entire container, I'd simply not specify any min/max constraints on it. Its "optimal" values are largely irrelevant, especially if the GUI theme has the ability to draw widgets of any size or scale.

The only part of sizing that is really important is how to determine to divvy up space among widgets. But as I've described before, even that is pretty easy to do with just a simple "default" or "requested" size. (It may or may not be "optimal," depending on the meaning you attach to that word.)

Edgar Reynaldo

Uh... I thought it was "it's" because that is how you specify ownership. I know it is not 'it is', but is it really "its"?

Matthew Leverton

The word its belongs with this group: hers, his, its.

The word it's is a contraction for it is or it has.

Oscar Giner

I've always wondered why English natives have so many problems with it's/its, there/they're/their... (maybe it's my impression, but it seems to me they're the ones who usually do those mistakes, not counting typos) :-X

append:
Now this makes me wonder too if people that are learning Spanish have problems with things like "haber" vs "a ver", usual typing errors here (both are pronounced exactly the same).

axilmar

That's the minimum size, not the 'optimum' size. An 'optimum' size can only be input by the user, not determined by the widget itself.

'Optimum' means 'most optimized' in this case, which is usually the smallest size that doesn't affect the widget's functionality.

Another example of optimum size, is the width of an line input widget with a set maximum of characters.

You mean a minimum number of characters, and I already talked about this case, in my previous post.

Quote:

This optimum size is dynamic, and can change while the app is running (button caption changes, for example). Min and max sizes are usually static (unless the user explicitly changes them).

Exactly. So, with my algorithm, when the caption of a button is changed, it will trigger the recalculation of all the dialog items, but only when it is required.

EDIT:

I think there's not really much here to argue. That is, I don't think any of you are actually disagreeing on any high level concepts... Practically speaking, the widget's true minimal drawing size is irrelevant to the programmer. Say I have a container with 100 pixels of space. I want to draw a button in there that I assign a minimal size of 150 pixels. The actual minimal size is, say, 30 pixels. So technically the button could fit in that 100 pixels of space.However, I've declared the minimum size to be 150 pixels. Thus the button should be drawn internally at 150 pixels but cropped to 100 when it goes into the parent container. It's my own fault if that wasn't my intention. If I wanted the button to fill the entire container, I'd simply not specify any min/max constraints on it. Its "optimal" values are largely irrelevant, especially if the GUI theme has the ability to draw widgets of any size or scale.

I think you have it a little backwards. A widget should really size itself to the minimum size that doesn't affect its operation, so as that the GUI leaves as much as possible useful work area to the user.

Take a button with text, for example: a button should show its whole text, otherwise it is not usable. So, the only thing a button should be required to do is to size itself according to its text and font that uses at the specific state (enabled, disabled, selected etc).

Now, if you want the button to be big and fill its parent container, the best approach is not to do it by the button itself, but with the parent container: it should be the parent container that decides how the button is ultimately sized.

This is the most flexible approach, because it allows children widgets to have the mimimum possible size, unless their parent says otherwise.

In the case of buttons, for example, with this technique, you can make button containers that:

  • size the buttons equally both vertically and horizontally, and places them into a row or column. For example, the buttons of a dialog box.


  • wrap itself around the button; for example, adding a resizing border.


  • resize the button to a specific size.


  • resize the button to expand itself to the available space left by its parent.

etc.

Oscar Giner
axilmar said:

You mean a minimum number of characters, and I already talked about this case, in my previous post.

No, I mean that the number of characters that can be typed has a maximum. For example, a line edit for inputting a year would have a maximum number of characters of 4. So the optimum width would be the needed to display 4 characters (usually, 4 "W" or "M").

Append:
In Qt, wisgets don't size themselves to their optimum size, but the have a sizeHint() function that returns this optimum size. So the parent takes full responsibility of sizing.

axilmar

No, I mean that the number of characters that can be typed has a maximum. For example, a line edit for inputting a year would have a maximum number of characters of 4. So the optimum width would be the needed to display 4 characters.

Nope, because if the maximum number of characters was 3000, the optimum width would not be for 3000 characters.

You are talking about the minimum number of characters.

Quote:

In Qt, wisgets don't size themselves to their optimum size, but the have a sizeHint() function that returns this optimum size. So the parent takes full responsibility of sizing.

This doesn't change the essence of the layout algorithm.

Oscar Giner
axilmar said:

Nope, because if the maximum number of characters was 3000, the optimum width would not be for 3000 characters.

You are talking about the minimum number of characters.

I'm talking about how Qt does it, and yes, the optimum size is set that way. If the maximum numbers of characters is 3000 then the optimum size will just not be possible to acquire and a smaller size will be set.

<quite>
This doesn't change the essence of the layout algorithm.
</quote>
Did I say something? You take it as is anything anyone says is to go against you. I'm just giving ideas, different ways of doing things.

axilmar

I'm talking about how Qt does it, and yes, the optimum size is set that way. If the maximum numbers of characters is 3000 then the optimum size will just not be possible to acquire and a smaller size will be set.

In your example, the optimum size is the number of characters for a Year, not the maximum characters.

Quote:

I'm just giving ideas, different ways of doing things.

No problem with that, I just wanted to point out that's the end result is the same.

Matthew Leverton
axilmar said:

I think you have it a little backwards. A widget should really size itself to the minimum size that doesn't affect its operation, so as that the GUI leaves as much as possible useful work area to the user.

I call that the "default" size. If you don't care as the programmer, never call the resize method on the widget. It then keeps its default, minimal size.

Edgar Reynaldo
axilmar said:

'Optimum' means 'most optimized' in this case, which is usually the smallest size that doesn't affect the widget's functionality.

AKA, the minimum size. I call that the minimum size because if it were any smaller it wouldn't function properly.

Oscar Giner

AKA, the minimum size. I call that the minimum size because if it were any smaller it wouldn't function properly.

Take a line edit for example. An optimal size may be such that it can display 10-15 characters. It's minimum size will be the required to display a single character.

The optimal size is determined by the widget, the minimal size (in most cases it defaults to the optimal size) can be changed by the user. The actual minimum size of a widget will be MAX(minimum size, optimal size).

Edgar Reynaldo

The point is, your 'optimum' size is pretty much arbitrary. One user would prefer 10 characters of space available, another would prefer 20. It's better to leave that up to the user, and not try to guess, because you could never make it work as a one size fits all solution.

Trent Gamblin

That's kind of the point of layout. The user can resize the window if they want more or less space.

Matthew Leverton

Take a line edit for example. An optimal size may be such that it can display 10-15 characters. It's minimum size will be the required to display a single character.

I thought non-native speakers didn't make the "it's" mistake. :-/

I agree with Edgar on this. Or at least, I understand his disagreement. I don't care what you call it, but there are two distinct concepts:

  1. the smallest size the widget can possibly draw itself while still being useful

  2. the ideal size the widget should be

The smallest possible size is of no concern to the programmer. It's only so the widget doesn't draw something silly looking or divide by zero or some other nonsense. If the visible size is smaller than the minimum size, then the widget can simply be cropped.

The ideal size is often arbitrary, and depends on the use case.

The programmer must be given a way to change the default size that a widget thinks it should be. You can do it via the layout manager or the widget or some combination. With all the fuss over terminology, I'm not even sure how you all are even suggesting that a programmer gain that control.

I chose to use a resize() function that changes the default size. If you don't use a layout manager, then that's what you get. If you resize to 2x2, that's all you'll see on the screen. If it's smaller than the widget's internal minimum size, then the widget will operate internally as if it's its minimum size, but only the 2x2 top left corner will be visible.

If you do use a layout, then the requested size is simply used as the initial size on the first pass. It's subject to be made bigger or smaller at the layout's whims.

But never does the minimum internal drawing size ever actually play a role in determining how much space the widget gets in a layout.

axilmar

I prefer layout management pretty much the way ML describes it: the resize() method resizes the widget to a specific (width, height) size, but the layout ultimately decides what the actual widget's size will be.

billyquith

... I have really never understood what a layout manager would actually do. ...

It is so that you can position and size your widgets automatically. This can very useful in resizable windows, or where you have to UI designer. You basically choose some rules and the layout class applies them to the child widgets.

It is important that the layouts are separate from the widget implementation (i.e. they refer to existing widgets without being part of their implementation). The layout is nothing to do with appearance or function. They are merely helper classes. Separating the layout code easily allows to add lots of different or custom layouts later.

Edgar Reynaldo

I'm still not exactly sure how I would integrate a Layout Manager into my current GUI setup. All widgets are derived from a common base, and there is a Widget Handler widget than handles all their input, update, and display routines. Would I give each Widget Handler a pointer to a Layout Manager base that the user can set? How do I handle nested Layout Manager's? Specifically, how do I handle adding widgets to a layout manager that contains another one? Say the first is a horizontal layout widget, and the second cell is another layout manager that is vertical. When I add the second, third, and other widgets to the first layout manager do they all get added to the second cell or do some go to the third horizontal cell? How would I know what to do? Set a limit on the number of cells in the vertical layout manager?

I just need some more practical ideas to get my head around how this would all work.

Matthew Leverton

My widget hierarchy goes something like: Object -> Widget -> Container. Every Container has exactly one Layout object. By default that object is NullLayout, which does nothing.

Widgets can only be added to widgets that derive from the Container widget. Adding a widget directly to a container is just a shortcut for adding it to that container's layout. Thus these are the same:

algui_add(parent, widget);
algui_add_to_container(parent->container, /*cell number*/ 0, widget);

But you must use the second method if you want to specify a cell number to use, so generally the first method is only used when you are using absolute positioning (NullLayout).

I allow you to add a layout directly to another layout for nesting purposes. But you could also do it by creating a transparent Container object that is used for no purpose other than sub layouts.

In your example you would:

  • Create the horizontal layout with two (or more) cells

  • Create the vertical layout with two (or more) cells

  • Add widget #1 into the horizontal slot 0

  • Add vertical layout into the horizontal slot 1

  • Add widget #2 into the vertical slot 0

  • Add widget #3 into the vertical slot 1

  • Set horizontal layout to be parent widget's layout manager

Note that you no longer need to explicitly add a widget to a container widget, because the layout takes care of that. It really doesn't add much complexity, because the layout can implicitly set the widget's parent pointer. i.e., Behind the scenes they can still be owned by the parent widget.

Then the layout would kick in and position all of the widgets. Any time you add something to the layout, you would then need to recalculate the widgets.

axilmar

I'm still not exactly sure how I would integrate a Layout Manager into my current GUI setup.

It's simple: make each widget a layout manager. Have grid widgets, horizontal box widgets, vertical box widgets, etc. Thus your example becomes really simple: just insert each widget in the widget you want.

billyquith

I'm still not exactly sure how I would integrate a Layout Manager into my current GUI setup.

Look at Qt. From memory that is nicely done. If you use the designer you can see how it is all supposed to work.

Someone else also cited Java. Have a look there too.

As mentioned by other posters, the layout widgets aren't really widgets, they are containers, which contain the widgets they are laying out. So they don't actually have an appearance, like buttons etc, they just do they layout. If you are unable to see how to do this with your current system you'll probably need to put more levels of abstraction in. Again, for guidance, see the Qt docs and hierarchy.

Edgar Reynaldo
axilmar said:

It's simple: make each widget a layout manager. Have grid widgets, horizontal box widgets, vertical box widgets, etc. Thus your example becomes really simple: just insert each widget in the widget you want.

That does not sound like an ideal solution. Maybe if each widget owned a layout manager, maybe, but that is still making the widget base class a container class, which IMO should be separate.

@Matthew
So basically, every layout manager is assigned a number of cells by the user, and then each cell is assigned a widget?

Matthew Leverton

Maybe if each widget owned a layout manager, maybe, but that is still making the widget base class a container class, which IMO should be separate.

Conceptually I agree. However, you may find that singular widget entities that cannot contain children still have multiple hidden children of their own.

You may have a push button that accepts an icon widget. Internally, you could use a layout to render that. i.e., Your push button could contain two children: a text label and an icon. It could use a horizontal layout to position things.

But since it doesn't extend from your Container class, a programmer couldn't actually add widgets to the button. Those sub widgets would never be seen or heard from, since the button widget would trap the events and re-emit the useful ones as its own.

I don't actually do that... but I sort of wish I had designed my GUI that way. Now that I have layouts, I may go back and change it someday.

Quote:

So basically, every layout manager is assigned a number of cells by the user, and then each cell is assigned a widget?

That's what I do. Since I use C and don't have overloading at my disposal, I just have a generic "add widget to cell #N" function. It's up to the container to treat that number appropriately:

  • Horizontal and vertical boxes are as expected.

  • Grids use N = y * w + x

  • Some layouts use constants like ALGUI_NORTH_CELL.

For some layouts, it might be useful to have "resize & append" functions. But usually a person knows ahead of time how many cells they need.

Edgar Reynaldo

@axilmar
I may have misunderstood what you meant. Did you mean make a set of widgets that are also layout managers? Or did you mean make every widget a layout manager? The first option I can understand, but I thought you were talking about the second option, which seems wrong.

jmasterx

I think the idea is that any Widget that derives from Container will have layout management capabilities.

I personally quite like how Java does Layout management.

Edgar Reynaldo

I think a widget container and a widget layout manager should still be separate. In my GUI, the container manages updates, input, and display, along with things like focus, hover, and z-order. If I used layout managers, the widget handler (container) would have a pointer to a layout manager. I think the two responsibilities should be kept separate. The container class does enough as it is already.

axilmar

That does not sound like an ideal solution. Maybe if each widget owned a layout manager, maybe, but that is still making the widget base class a container class, which IMO should be separate.

Actually, making the widget class a container class is the right thing to do. It simplifies the design tremendously.

Very few resources are actually saved by not making the base widget class a container. Suppose the average desktop application contains 1000 different widgets (overestimated by a large amount), and a container class has 16 bytes more than the non-container class, then the resources saved are 16000 bytes. 16K for a modern desktop computer is nothing. It's even nothing for the lamest of phone devices.

I may have misunderstood what you meant. Did you mean make a set of widgets that are also layout managers? Or did you mean make every widget a layout manager? The first option I can understand, but I thought you were talking about the second option, which seems wrong.

What I mean is this:

  • each widget has the necessary virtual methods to support layout management.

  • specific widget subclasses actually implement those virtual methods.


    I think a widget container and a widget layout manager should still be separate. In my GUI, the container manages updates, input, and display, along with things like focus, hover, and z-order. If I used layout managers, the widget handler (container) would have a pointer to a layout manager. I think the two responsibilities should be kept separate. The container class does enough as it is already.

    But adding a layout management interface to a widget is a very small thing to add to a class. By making layout managers separately, you complicate the API without needing it to be so.

For example, in Qt, you should not only put a widget inside another widget, but also add it to the layout manager of the parent widget.

Compare Qt's approach with mine: all you have to do is to add one widget in another.

Managing layouts on top of widgets adds a lot more complication that shouldn't be there. You have to carefully manage pointers from widgets to widgets, from widgets to layouts, from layouts to widgets and from widgets to layouts. The user of your API will have to make double the effort in constructing a GUI: he will have to put one widget inside the other, then instantiate layouts, put those layouts in widgets, then add the children widgets to those layouts. Having no separate layouts is a win-win both for the library designer and the library user.

If you want to see how I do layout, you can browse my gui's code in github. I'll be glad to answer any question you might have.

Oscar Giner
axilmar said:

each widget has the necessary virtual methods to support layout management.

specific widget subclasses actually implement those virtual methods.

Do you mean that each kind of container must fully implement layout management? How is that better than having layout classes that work with any container? If I, as a user, want to implement my own container, this means I must also implement layout management? And for containers already implemented, how can I add a different kind of layout?

CAn you show us a small example of your API, because I think I don't really understand what you mean? Just a main window, with a box layout and 6 buttons organized in a 3x2 grid, for example.

axilmar

Do you mean that each kind of container must fully implement layout management?

No. The base container class may implement no layout management, it can only provide the interface for derived classes.

Quote:

If I, as a user, want to implement my own container, this means I must also implement layout management?

No. You just create a derived class from the container widget of your choice.

Quote:

And for containers already implemented, how can I add a different kind of layout?

Create a derived class and override the appropriate methods.

Quote:

CAn you show us a small example of your API, because I think I don't really understand what you mean? Just a main window, with a box layout and 6 buttons organized in a 3x2 grid, for example.

Sure. I do not have an implementation yet in my current effort, but I did various GUI libraries in the past that did this:

Window *mainWindow = new Window();

//the grid widget is a child of main window
Grid *grid = new Grid(mainWindow, 3, 2);

//the buttons are children of the grid window
Button *button1 = new Button(grid, "button 1");
Button *button2 = new Button(grid, "button 2");
Button *button3 = new Button(grid, "button 3");
Button *button4 = new Button(grid, "button 4");
Button *button5 = new Button(grid, "button 5");
Button *button6 = new Button(grid, "button 6");

jmasterx

That's basically how my GUI works too:

agui::FlowLayout* layout = getGuiFactory().createFlowLayout();
getGui().add(layout);
agui::Button* button = getGuiFactory().createButton();
layout.add(button);
button->setMargins(5,5,5,5);
button->setSize(200,50);
button->setText("Hello");

The gui factory manages the memory, this makes it much easier to skin and deal with everything.

The FlowLayout inherits from Layout and Layout inherits from Widget. For my needs, this is perfect.

Oscar Giner

Ah, I see. So you have two different objects, first the mainWindow itself, and then the layout manager (Grid in this case). I first understood that the container (mainWindow) would also implement the layout management. So the only difference between this and Qt's way, is that in your case the layout classes also inherit from Widget.

This effectively makes everything easier to implement. The only drawback I see is that layouts now also get messages and must ignore and pass them up in the chain. Layout managers should not know about that.

Edgar Reynaldo
axilmar said:

Actually, making the widget class a container class is the right thing to do. It simplifies the design tremendously.

I would have to disagree. I would say that making widgets that are also containers is okay, but making every widget a container seems wrong. It doesn't lead to good separation of code, and it doesn't sound very OOP to me. It sounds like a messy monolithic class. I know that a lot of code goes into both the widget base and the container base, and I wouldn't want to combine the two.

It's not about saving resources in this case, but it is about separation of duties and code, and keeping code organized and logical.

Matthew Leverton

Come to think of it, I think my hierarchy may go like: Object > Widget > Composite > Container. The composite class introduces children and a layout manager, while the container class exposes a public API to add children.

axilmar

It's not about saving resources in this case, but it is about separation of duties and code, and keeping code organized and logical.

Believe me, I've been there, I've created libraries and coded in libraries that have a separate container class from a widget class. The separation between container and widget complicates things ten times more than it need be, and you don't gain anything in reality, since the basic Widget class will need to have a Layout management interface anyway.

You don't even get more logical and organized code by this separation, because the base class Widget will have to have virtual methods that are about the container.

Thread #608404. Printed from Allegro.cc