I started making a game and realized I needed a decent interface so I first had to build a GUI. I know that I'm reinventing the wheel, but it's a learning experience.
Here is the current output for the dialog(form) editor with one of the dialogs opened:
{"name":"608296","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/4\/7\/478137f77e667ef59b1bdcf38f1e0b9d.png","w":1600,"h":900,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/4\/7\/478137f77e667ef59b1bdcf38f1e0b9d"}
I use XML for the storage and retrieval. Here is the file 'layout.xml' for the above image.
While reading another post, I came across a couple of questions.
1) manual memory management. It's 2014 for crying out loud, use smart pointers! :-)
I first tried to build it using smart pointers, but had a problem. Maybe you could point
me in the right direction. My GUI relies on inheritance of a base widget class and uses containers i.e. lists, vectors, ...
Using pointers, I could do something like this (pseudo-not tested)
std::list<widgetBaseClass*> list; list.push_back( new derivedWidget() );
but this would cause an error "could not convert blah, blah"
std::list<widgetBaseClass> list; list.push_back( derivedWidget() );
How would I be able to do this without using pointers?
5) using ids. Bleh. Lessons not learned from MFC.
Confused on how would you access object without linking some sort of id to it?
std::list<std::unique_ptr<widgetBaseClass>> list;? (or shared_ptr)
Edit: Update to a new version of VS?
The pointer version should not give an error. What is the error?
You still need to use pointers, but you can use smart pointers which use RAII to automatically clean up your objects when the last references to them go out of scope. See boost::shared_ptr and family for example (or with C++0x/C++11x, std::shared_ptr).
You will need to make sure that all of your classes have virtual destructors for all destructors to be called, but that would have been true with the base pointers in an STL container too.
As for the widget identifier thing, without linking back to the original thread, you're kind of taking axilmar's comments out of context. I'd say that a widget id probably does make sense if you want to have completely dynamic GUIs.
std::list<widgetBaseClass*> list;
list.push_back( new derivedWidget() );
but this would cause an error "could not convert blah, blah"
This should work.
Check this: if you use forward declarations, some part of your program might not be aware that derivedWidget is actually derived from widgetBaseClass. Include headers instead of forward declarations where needed.
EDIT: I just noticed that I misunderstood you, and you meant that you can do this with pointers, but you wanted to do the same thing with stack objects (well, I think they use pointers anyway internally, but you know what I mean).
In this case, as already mentioned above, you should use std::shared_ptr or something similar.
The reason it does not work on the stack is because the compiler can't know how much memory it will need for your object until you tell it exactly which kind it is.
Ok, I upgraded to C++011. Looking at axilmar's c++ allegro wrapper and his shared pointers, things are starting to make more sense.
Thanks everyone.
Now I have to rewrite(update) my personal libraries that I use. Oh well.
I abhor the fact that we all have so many separate gui's. If we could have spent half as much of the time working together that we had worked on our own libraries we could have something rivaling QT or WxWidgets.
I wish I could get some of you guys to join in on my EAGLE library. I just need more time to port all my widget classes - I already have a good flexible foundation for a great gui library which will work for any backend once you write a driver (a5 driver complete) I've got automatic resource handling so you don't need to do anything except delete your system driver when you're done with it. Right now I need to implement skinning and a couple more layout managers and then I will start porting my widget library to use the new system. I've got a separate thread running for events, and there is full setup with like three lines of code - 1)new a system, 2)Initialize the system (bitfield containing options returning options initialized properly) 3) create a graphics context and then draw away. You can pull events directly from the system or make your own queue. And if I added in tiny xml I could support gui specs in xml files, and have each widget implement serialization to / from xml like DanielH does.
Point in proof -------------------------------- Mark Oates - FLARE gui Axilmar - algui TrentG - TGUI Supreme Loser - C based GUI jmasterx - AGUI Mois - Eagle gui DanielH - XML gui
and I'm sure there are more I've missed.
I'd say your initiative falls apart where you expect everybody to work on your library. If you were serious about a collaborative project you wouldn't give it a name, and wouldn't give it a single base or any bounds at all, and would work on something new or agreed upon. In the end, you'd all have to reach a consensus before development could happen, and that would mean compromises from everyone.
The thing is we've all got a solid base, but we may each cover different areas of widget and gui programming, and yes I would like people to help on mine and yes I am willing to help with others. My code is freely shared with others as long as you give me credit. I don't think starting over from scratch is what any of us want to do. Rather we should try to integrate or merge our libraries capabilities together.
Maybe I should start a kickstarter project.
Nobody wants to start from scratch, but you can't "merge" completely different projects together. For all intents and purposes, most of you have probably done similar things, but in incompatible ways. There is no copy and paste. You have to assess the good and the bad design decisions and as a group decide what works and what doesn't, what is necessary, and what is expendable, etc. It might work to start from somebody else' base, but it is presumptuous to assume it will be yours. You can all expect to lose things you find necessary during the planning phase. That is what working in a group is like. If you aren't willing to make sacrifices then you can't expect anyone else to, hence there are 10 or more GUI projects for A5.
I never assumed it would be mine, but I don't want my code to go to waste any more than any one else does. I've put a lot of time effort and thought into this library and I believe it is well designed. It is easily modified, the code is clean and commented where necessary and no strange hungarian bs is used. I will admit it lacks docs of any kind. The design is simple polymorphic inheritance from base classes. It is fully capable of dirty rectangle drawing which is still useful these days at times. Events are supported. Listeners are supported. Signals and slots are not supported at this time, but axilmar already did that the other day as long as you upgrade to C++11.
And I have been looking for someone to join my team for some time and I won't apologize for advertising what I think to be a fine library. For better or worse, my hat's in the ring.
What about you bambams? You got anything other than your opinion to put in the hat?
edit
and anecdotally, I did have someone express interest working with me a while back, but then he disappeared. oh well
Edgar, I would add to your list that Max Savenkov has tried to integrate Qt and Allegro (here) and succeeded to a point....someone asked the same for wxWidgets IIRC....and that there ARE out there a LOT of GUIs not seeded from Allegro itself (myGUI, CEGUI, GWEN..)
I said that... nowadays GUIs are popular.
I have to say that I don't understand bam's post:
I'd say your initiative falls apart where you expect everybody to work on your library. If you were serious about a collaborative project you wouldn't give it a name, and wouldn't give it a single base or any bounds at all, and would work on something new or agreed upon. In the end, you'd all have to reach a consensus before development could happen, and that would mean compromises from everyone.
Where did Edgar say that he expects anybody to work on his library?
I see your point Bam, but Ed makes a vlid point even thou...eh...teamwork is serious business.
Edgar, I would add to your list that Max Savenkov has tried to integrate Qt and Allegro (here) and succeeded to a point....someone asked the same for wxWidgets IIRC....and that there ARE out there a LOT of GUIs not seeded from Allegro itself (myGUI, CEGUI, GWEN..)
I was just making a point about what we could have accomplished had we worked together from the beginning.
Shots fired.
Maybe you could point
me in the right direction. My GUI relies on inheritance of a base widget class
Use std::shared_ptr<Widget> instead of Widget*.
and uses containers
std::shared_ptr<Widget> will work fine with containers.
How would I be able to do this without using pointers?
You can't do it without pointers.
Confused on how would you access object without linking some sort of id to it?
The pointer to the object is the id you want.
I abhor the fact that we all have so many separate gui's.
Me too.
If we could have spent half as much of the time working together that we had worked on our own libraries we could have something rivaling QT or WxWidgets
No shit. I've been begging you for at least a few years to work collectively on an Allegro gui but you've always ignored me.
I wish I could get some of you guys to join in on my EAGLE library
I am on.
I already have a good flexible foundation
Nope. Let's start over and use whatever makes sense from each of our library. We should decide collectively on what feature is good/bad, based on voting.
Do you agree Edgar?
and anecdotally, I did have someone express interest working with me a while back, but then he disappeared. oh well
All you can really do is put your project out there. If people want to help, they'll help.
All you can really do is put your project out there. If people want to help, they'll help.
That's not all you can do. We can have a dialog about the design of your GUI app and what makes it good or not...that is if you want participation in a group effort.
That's not all you can do. We can have a dialog about the design of your GUI app and what makes it good or not...that is if you want participation in a group effort.
I was talking about how most projects get contributors. They do it because they want to, or are being paid to.
Having a discussion about a hypothetical group effort is not quite the same. Might be useful to some of the participators, but the likelyhood that a full fledged joint project comes out of it is pretty low.
Nope. Let's start over and use whatever makes sense from each of our library. We should decide collectively on what feature is good/bad, based on voting.
Do you agree Edgar?
We need somewhat of a review period to look over code and see what features we have or are lacking in each of our guis. We should try to reuse code as much as possible. axilmar, have you ever looked at my gui? I mean, like in full detail. There's far much more to my library than being a gui. Let me make a commit when I get home first though.
There's far much more to my library than being a gui. Let me make a commit when I get home first though.
Ok, please let me know when you make the commit, and I will have a look.
Perhaps start by looking at each GUI and list what each does well and does not do well.
From there, possibly list what the new one should and should not do.
From there, design the core API, possibly design it around the one that is most like what you want.
As long as the initial design is solid and modular, a pretty epic and feature-rich API can be built around it. Borrowing as much code as possible from other APIs.
Here ya go.
------------
svn checkout "svn://svn.code.sf.net/p/eagle5gui/code/trunk eagle5gui-code"
There are CB projects included for MinGW and stub CB projects for Linux (haven't done the linking yet).
I think of most interest would be InputHandler.cpp/hpp, System.cpp/hpp, GraphicsContext.cpp/hpp, Events.cpp/hpp, Error.hpp, Logging.hpp, and maybe others.
I applaud you Edgar for the effort, but there are some really big problems with your code.
If you are going to be pissed off, then please don't read further.
Anyway, here is a list with some issues I quickly found out from first glance:
there is no reason to put yet another multimedia layer on top of Allegro, especially if the new layer matches 99% that of Allegro. If a platform does not support Allegro, porting Allegro to it would suffice. The GUI must be built on top of Allegro. For example, your event id list matches 99% that of Allegro. That's not enough abstraction to justify yet another layer on top of Allegro. Your event source organization matches that of Allegro exactly. Again, not enough justified abstraction.
huge files with many classes in it. I am struggling to find where classes are declared.
widget messages. No widget messages please, this is 2014 and c++ has virtual methods for this reason.
many globals.
much use of bare pointers. We shall use std::shared_ptr anywhere.
no namespaces.
some classes are prefixed with Eagle, some are not.
instances of classes with virtual methods are passed as values to functions instead of constant references.
no documentation in the headers. I am opening a file, and I see lots of declarations without comments explaining what they do.
primitives like Rectangle having virtual methods. Is it necessary to have such small scale classes be virtual?
classes returning STL containers of pointers to objects in them. Who is supposed to free those objects? why aren't they wrapped up in manager objects? (the correct approach would be to be use std::shared_ptr/std::unique_ptr).
off-putting syntax. For example, property names with capital letters.
layout classes shouldn't be widgets. Each widget should be connected to a layout class which allows for greater reuse of layout algorithms and widgets.
methods prefixed with Private shouldn't be protected.
why is there a Camera class?
widgets shouldn't have a display priority. A simple z-order suffices.
class EagleColor has both integer r, g, b members and float r, g, b members.
the class PointerManager is a code smell. If you want to automate memory management, there is only one way to do it in c++, and that's smart pointers.
the naming of the classes is not that good. For example, you have a class EagleEventListener and right next to it a class EagleEventHandler. How do these two differ? it's not easy to tell by the name.
where are the rest of the widgets? I only found an incomplete button there. Was I looking at the wrong code?
many standalone functions without namespace or class.
Mind you, all the above are just from the headers.
I suppose now you will think "WTF?"
Please don't take this the wrong way. I really really applaud you for the effort. But I can't make you believe that I think your code is the best we can do. We can do much much better. We can make much simpler, more reliable, more readable c++ code.
Is shared_ptr really required though, wouldn't a simple unique_ptr be sufficient?
I think unique ptr would just let you keep your widgets stack allocated, whereas I think shared_ptr would be useful for listeners and other weak reference usages.
There are many cases that you need a shared pointer to a widget. For example, a container widget contains a list of widget pointers, but your container subclass contains pointers to specific widgets that are also on the parent's widget list.
widget messages. No widget messages please, this is 2014 and c++ has virtual methods for this reason.
That is entirely just a style preference. I'd prefer having a low level widget message, which then is used to implement a higher level system like listeners or sigslots. Rather than a crap load of virtual method calls.
Rather than a crap load of virtual method calls.
A crap load of virtual method calls is a code smell. You can design GUIs without such a code smell.
Usually that's done by limiting functionality.
Usually that's done by limiting functionality.
I don't think so, but perhaps there is a case I have not thought about. Do you have an example? (aside from win32 which imposes Objective-C style OOP onto C objects).
I don't have time to reply fully, but I will say a lot of the things on your list are on my todo like namespaces, and no I won't abandon widget messages, that is the basic form of communication among the gui. I don't need a thousand different onMySpecificCallbackForThisFunction methods and two it centralizes input to a single source which is cleaner code. Your widgets input functions will usually not be more than a couple pages of code for simple widgets anyway.
That is entirely just a style preference. I'd prefer having a low level widget message, which then is used to implement a higher level system like listeners or sigslots. Rather than a crap load of virtual method calls.
Yes I agree.
there is no reason to put yet another multimedia layer on top of Allegro, especially if the new layer matches 99% that of Allegro. If a platform does not support Allegro, porting Allegro to it would suffice. The GUI must be built on top of Allegro. For example, your event id list matches 99% that of Allegro. That's not enough abstraction to justify yet another layer on top of Allegro. Your event source organization matches that of Allegro exactly. Again, not enough justified abstraction.
Yes you do need an abstraction layer so your widgets can use a virtual graphics engine. The whole reason I designed it this way was so you could use multiple different backends, even simultaneously in the same program. The reason it matches Allegro so closely is merely for convenience porting code to Eagle from Allegro 5. I assure you it will be quite different for different engines I will have to map their events to my own and so on.
I will respond fully later but I have class now.
and no I won't abandon widget messages, that is the basic form of communication among the gui. I don't need a thousand different onMySpecificCallbackForThisFunction methods
If you design your gui properly, you will never ever reach a state where you need a thousand different onMySpecificCallbackForThisFunction methods.
two it centralizes input to a single source which is cleaner code
All you need is a dispatch-allegro-event method on your widgets. You certainly don't need messages.
Yes you do need an abstraction layer so your widgets can use a virtual graphics engine.
Allegro is the abstraction layer.
The whole reason I designed it this way was so you could use multiple different backends
You don't need that, since Allegro provides the abstraction.
even simultaneously in the same program
Not needed.
The reason it matches Allegro so closely is merely for convenience porting code to Eagle from Allegro 5. I assure you it will be quite different for different engines I will have to map their events to my own and so on.
If you define different event ids for other engines, then your abstraction has failed.
If you map the events of other systems to your events that look like Allegro events, then Allegro does exactly that. There is no need for code duplication.
Anyway, there is no need for this to go on. You clearly do not wish to make an effort to understand anything beyond your own design decisions, and I am sure you will respond to this in the way you did before, i.e. not understanding what I am saying, so simply forget it. It's just a waste of time.
If you can't even get past the fact that I want my gui library not to be dependent on allegro, then I don't know how we'll ever get anywhere. 
Edit-
I forgot to say the widget library is in an earlier version of my eagle library, that works with allegro 4. Ie. I still need to port them to the new system.
svn checkout "svn://svn.code.sf.net/p/eaglegui/code/trunk eaglegui-code"
If you can't even get past the fact that I want my gui library not to be dependent on allegro, then I don't know how we'll ever get anywhere
I understand that, although there is no reason to do so.
Do you understand that if you adopt the Allegro 5 semantics then your effort is redundant and you might just use Allegro 5 as the backend?
I also wanted an SDL backend, as well as possible SFML, and maybe even Cairo. That way people can use their favorite graphics library right alongside eagle with no problems.
I also wanted an SDL backend, as well as possible SFML, and maybe even Cairo. That way people can use their favorite graphics library right alongside eagle with no problems.
And the event ids for SDL would be these?
Nevermind, I see the problem.
And the event ids for SDL would be these?
No, there would most likely be an EAGLE_EVENT_TYPE GetEagleEventType(SDL_EVENT_ID); function.
If you define different event ids for other engines, then your abstraction has failed.
No, not at all. I can either support the union of the two libraries event abilities or the superset and have some functionality disabled for specific backends.
Yes you do need an abstraction layer so your widgets can use a virtual graphics engine.
Allegro is the abstraction layer.
Not if I want to drive the system with SDL for example, then Eagle would still be the abstraction layer. If I want to say win->DrawLine(x,y,x2,y2,EagleColor(0,0,255,125), 2.0); in my widget then the graphics context can either call allegro's draw line routine, or sdl's draw routine. It is no longer bound to allegro. This is the whole reason I abandoned my earlier gui engine was because it relied on Allegro 4. Now I could support Allegro 4 or 5 if I wanted to. The flexibility is what I wanted.
Anyway, there is no need for this to go on. You clearly do not wish to make an effort to understand anything beyond your own design decisions, and I am sure you will respond to this in the way you did before, i.e. not understanding what I am saying, so simply forget it. It's just a waste of time.
Well clearly all you can do is criticize and if you don't want to hear my responses then why do you ask me questions? Merely to state your opinion and ignore mine? Were there even any features of my gui that you thought were worth keeping?
I have to go with Edgar on this. I could never bring myself to writing an API just for Allegro.
Abstraction makes sense. The similarities to Allegro 5 cause minor alarm. It suggests that you lack a higher-level knowledge of the problem domain and are copying what you know. Which sort of defeats the purpose of abstraction. If you just duplicate Allegro then you'll at best accomplish nothing new and at worst duplicate the Allegro developers' mistakes. Additionally, you may find that it's difficult to implement backends for other libraries if they aren't structured similarly to Allegro. It could be that the other backend implementations are such major hacks that performance is atrocious and the backend is unusable. Which sort of defeats the purpose. I haven't looked into your implementation so I'm just taking axilmar's comments at face value, but I would suggest you aim to strive away from Allegro. Perhaps learn SDL or whatever. Familiarizing yourself with other planned backends will help you to recognize the common elements between them. You basically have to prioritize. You either want to make something backend independent or you want to build an Allegro GUI. You can always add the abstractions after. It is software for a reason.
The arguing is more or less what I expected. It is probably a necessary stage to work through. Like I said, everybody thinks that their shit doesn't stink, but everybody thinks that everybody else' shit does. If you want to collaborate then you have to make sacrifices. Accept that what you build together won't be perfect, and figure out what will be good enough. Try to learn from one another instead of trying to prove superiority over one another. Protip: You're all wrong. Now you get to explore how each of you is wrong, but at the same time, sometimes, each of you is a little bit right.
Allegro is far from perfect. A GUI doesn't have to be perfect to be useful. Make yourself willing to fail and you just might make something useful. You'll surely learn along the way, which will increase your chances of getting it perfect next time.
It's getting a little hot in here!
Perhaps now is not the best time to bring up the topic
of writing the GUI library in C so that it's usable
by everybody (C,C++,OBJ-C) ?
I'd say that it's a reasonable point to make, especially since Allegro is C.
Writing a gui library using C comes at a price though - you sacrifice inheritance and function overloading for the sake of binary compatibility. Which is fine if you like that sort of thing. Matthew wrote a C gui library with A5 as I believe I stated above. You might want to see how far he got.
Abstraction makes sense. The similarities to Allegro 5 cause minor alarm. It suggests that you lack a higher-level knowledge of the problem domain and are copying what you know. Which sort of defeats the purpose of abstraction. If you just duplicate Allegro then you'll at best accomplish nothing new and at worst duplicate the Allegro developers' mistakes. Additionally, you may find that it's difficult to implement backends for other libraries if they aren't structured similarly to Allegro. It could be that the other backend implementations are such major hacks that performance is atrocious and the backend is unusable. Which sort of defeats the purpose. I haven't looked into your implementation so I'm just taking axilmar's comments at face value, but I would suggest you aim to strive away from Allegro. Perhaps learn SDL or whatever. Familiarizing yourself with other planned backends will help you to recognize the common elements between them. You basically have to prioritize. You either want to make something backend independent or you want to build an Allegro GUI. You can always add the abstractions after. It is software for a reason.
Exactly. Well said.
I am fully in favor of abstraction. Who wouldn't be? It would be nice to have a new gui library that can be used with any graphical subsystem.
But that is a tremendously difficult task. wxWidgets and Qt probably have millions of man days of work behind them, and they do not take into account games. We should not fool ourselves that we are capable of going that route.
of writing the GUI library in C so that it's usable by everybody
I have no problem with that, although C++ makes things so much easier and safer to the point that it makes using Objective-C redundant.
Abstraction makes sense. The similarities to Allegro 5 cause minor alarm. It suggests that you lack a higher-level knowledge of the problem domain and are copying what you know. Which sort of defeats the purpose of abstraction. If you just duplicate Allegro then you'll at best accomplish nothing new and at worst duplicate the Allegro developers' mistakes. Additionally, you may find that it's difficult to implement backends for other libraries if they aren't structured similarly to Allegro. It could be that the other backend implementations are such major hacks that performance is atrocious and the backend is unusable. Which sort of defeats the purpose. I haven't looked into your implementation so I'm just taking axilmar's comments at face value, but I would suggest you aim to strive away from Allegro. Perhaps learn SDL or whatever. Familiarizing yourself with other planned backends will help you to recognize the common elements between them. You basically have to prioritize. You either want to make something backend independent or you want to build an Allegro GUI. You can always add the abstractions after. It is software for a reason.
The similarities to A5 are simply due to the fact that the first backend I planned to implement was A5. When/if I get time to write other backends, I am sure the overall implementation will change to accomodate the new backend.
I don't care to be accused of copying libraries. If you had looked at the library you'll see the only thing that was really copied was the event definitions. As I don't know SDL or any other graphics library well at this point, there was no purpose making a whole bunch of different events. The events are the same as Allegro for ease in porting A5 programs to my library, nothing more. That will probably change once I write another backend, and I will translate allegro's events into my own then when necessary.
You either want to make something backend independent or you want to build an Allegro GUI. You can always add the abstractions after. It is software for a reason.
I want backend independence. That's why I designed my library the way that I did, with system and graphics drivers for abstraction layers. That frees my gui from dependence on any one backend. Adding the abstractions later would be like redesigning the engine of a car after it is already built. Pointless for the current car, but useful for the future. If I was to add the abstraction in later it would most likely be some sort of giant hack, because it wasn't designed into the library from the beginning.
I am fully in favor of abstraction. Who wouldn't be? It would be nice to have a new gui library that can be used with any graphical subsystem.
That's not what you said before. You said it was pointless to build a gui for allegro that wasn't built on allegro directly. And so you know, my library can be used with any graphical subsystem as long as you write a driver for it, and the backend is capable of implementing the core functionality. SDL should work with my library just fine, as its abilities are quite comparable to Allegro.
People swap car engines all the time... It's easier with software because the frame is far more malleable. In any case, you admit that your abstraction layer will probably need to change to accommodate other backends so that pretty much makes the current abstraction layer not really an abstraction at all, but a redundant layer.
In any case, you admit that your abstraction layer will probably need to change to accommodate other backends so that pretty much makes the current abstraction layer not really an abstraction at all, but a redundant layer.
WTF are you talking about? It's not redundant at all, if you had even bothered to look at my library. My library makes setup super easy, and provides everything you need to jump right into your program. An event handler is provided, and it is hooked up to all the inputs available in the system. There is a full input library which makes reading input super easy and convenient. There are debugging and logging abilities, as well as automated memory management. There's far much more to my library than the event definitions.
So what if the abstraction layer needs to change some? It works fine as it is, and I doubt it would have to change much to accomodate SDL. Perhaps more for SFML/Cairo, but I'm not as concerned with those. SDL and Allegro are the main graphics engines out there that I wanted to be able to support, as they seem to have the most longevity.
Without the abstraction, it would just be another library dependent on allegro. And as soon as Allegro 5 is irrelevant, so would be my library. That's what happened with Allegro 4, and is the whole reason I added the abstraction layer. If I had another driver written, I could run two programs simultaneously with different drivers, and compare the performance of the two. Try that without an abstraction layer.
Don't worry Edgar, a backend abstraction layer is a good thing 
GWEN and guichan both used the abstraction layer method. It's just a generally good idea not to tie down to a specific backend. It would be like if Allegro tied itself down to OpenGL or Windows.
When/if I get time to write other backends, I am sure the overall implementation will change to accomodate the new backend.
This is all I was referring to. If the abstraction layer needs to change in order to accommodate the other backends then it's not really an abstraction layer. It's a redundant layer (i.e., it doesn't serve a purpose yet, and will need to change before it could). Not trying to insult your library which I know nothing about (I admire your aspirations and efforts).
This is all I was referring to. If the abstraction layer needs to change in order to accommodate the other backends then it's not really an abstraction layer.
You have to start somewhere. Most people aren't going to sit down and look at all of the possible backends and design the ONE TRUE API that fits all of them. Most start with one or two, and will refactor as needed.
It's a redundant layer (i.e., it doesn't serve a purpose yet, and will need to change before it could).
By that definition, all unfinished code is redundant. Edgar's abstraction layer is simply incomplete.
so that pretty much makes the current abstraction layer not really an abstraction at all, but a redundant layer.
This is all I was referring to. If the abstraction layer needs to change in order to accommodate the other backends then it's not really an abstraction layer. It's a redundant layer (i.e., it doesn't serve a purpose yet, and will need to change before it could). Not trying to insult your library which I know nothing about (I admire your aspirations and efforts).
Exactly.
You have to start somewhere. Most people aren't going to sit down and look at all of the possible backends and design the ONE TRUE API that fits all of them. Most start with one or two, and will refactor as needed.
By that definition, all unfinished code is redundant. Edgar's abstraction layer is simply incomplete.
Refactoring is one thing, throwing away the code and starting over is another.
Why don't you people go review Edgar's code? you will understand what I and bamccaig is saying. Edgar has also incorporated Allegro event sources to his library. We are talking about design 1:1 to Allegro.
Come on people, let's quickly finish this round of discussion. Edgar's code may contain some good pieces, we may reuse them.
Why don't we open a design document for our GUI?
I've started one:
https://docs.google.com/document/d/1_epQPxQpJjUosAgUfKW3kGW9x5HBjuAlvmbmD7L3CYQ/edit?usp=sharing
You may also want to abstract away cursors. For example, Agui sets the cursor when mouse enters textbox. Possibly also transformations. Timers can be useful too but may be harder to abstract.
Transformations are useful if say, the native buffer size is 640x480 and the user goes fullscreen with that bitmap. You want the mouse to still correctly detect widgets.
Supporting UTF-8 is nice too.
For features, it could have all 3 messaging styles like QT:
-Messages
-Listeners
-Signal Slot
How you handle skinning is important too.
It would be nice if:
In the simple case, users can just supply bitmaps for each Widget (or one big one like GWEN allows). But in the more advanced case, the user should be able to override how a Widget both: Paints its background and its component.
When making Agui I realized the importance of having both.
This is where the idea of margins came into play.
So for skinning, all rendering could be done possibly using the Visitor design pattern http://en.wikipedia.org/wiki/Visitor_pattern or by creating a class with virtual methods: buttonPaintBackground(Graphics& g) ... etc.
This way the user can skin without subclassing all the widgets (One of the pitfalls of Agui).
Another interesting problem you need to think about is:
How do events bubble up. This is sort of another pitfall in Agui.
The event in Agui goes straight to the designated widget and all attached listeners.
But what happens if you have a TextBox with a scrollbar inside. The textbox needs to scroll itself when the scrollbar is scrolled. The only somewhat ugly way to do this in Agui is for the textbox to internally attach a listener to its scrollbar.(The even better way is to put it in a scroll panel).
There are a few better ways to handle this. Some GUIs send the event to the parent first, then if the parent is not interested, it is sent to the widget itself. Other guis will use the chain pattern:
http://en.wikipedia.org/wiki/Chain-of-responsibility_pattern
You will need to decide what is best and how listeners should consume events, etc.
Where this went most horribly wrong in Agui is my ScrollPanel widget. It attaches all kinds of listeners to its children to detect when to show / hide the scrollbars.
Added mouse cursors to the list of things to abstract.
For the rest you mention, I updated the document.
Why don't you people go review Edgar's code? you will understand what I and bamccaig is saying. Edgar has also incorporated Allegro event sources to his library. We are talking about design 1:1 to Allegro.
What are you talking about? Event sources copied 1:1? Here is my EagleEventSource header :
That is certainly not a 1:1 copy of anything.
And if you're talking about using ALLEGRO_EVENT_QUEUE's inside the Allegro5EventHandler, why not? It's an a5 driver, it should be using a5 functionality. I used the same names and values for events to make it easier to port from a5 to my library. All they have to do is rename their events to EAGLE_ instead of ALLEGRO_. And the id values are the same so I can just perform a simple assignment of the variable value instead of having to map to different values. :/ That is pretty much the only thing that is the same about my library and allegro 5. If I didn't use ALLEGRO_EVENT_QUEUE's internally I would have had to implement a separate thread for every input source instead of one thread per event handler. And I would have had to implement some version of locking and sleeping using pthreads on top of it then.
I attached both Events.hpp and Allegro5EventHandler.hpp. Look for yourself and see.
That is certainly not a 1:1 copy of anything.
The idea of having an event source is a copy of Allegro's relevant idea. I didn't say you copied the implementation.
Let's stop with this nonsense and collaborate on a GUI. Did you read the design document I started? you can edit it if you wish.
We can bring anything we need from EagleGUI into the new GUI, if it's good and available.
The document looks good. However, I have an alternate suggestion for skinning. You seem to imply that the Widget class has a virtual setSkin. This means the user needs to subclass the Skin class for each widget they want to custom render since it is per-Widget. Instead, it might be better if you have setSkin in your Gui class of sorts. This way calling gui.render() will actually do:
for each widget widget.paintBackground(skin,g); widget.paintComponent(skin,g); ... Widget::paintBackground(Skin s, Graphics g) { s.paintBackground(this,g); }
This sort of thing is possible with the visitor pattern and double dispatch.
A user should be able to subclass Skin and custom paint any and all widgets without having to subclass the skin class for each widget.
Your way may be able to do this and I may have misunderstood. I apologize if I did. But one of the caveats of Agui is having to subclass all Widgets just to paint them in a custom way. It would be cool to have something more like Java Swing.
This means the user needs to subclass the Skin class
No, the Skin class would not need to be subclassed. It's a resource manager. Each widget will know how to get resources from it and apply it to its painting algorithm.
Design doc looks like a great start.
Requested Additions:
-drag and drop.
could we also support DnD across different ALLEGRO_DISPLAY's?
-a default event loop to give control to GUI
-input injection methods for all input devices.
for people who want to manage input themselves
-gesture support
phase #1: as supported by platform
My idea for skinning was to have each widget own a widget area object that has a background component, and 9 panels ie center + margins. All you do is call WidgetBase::Draw in your SubClassWidget::Draw method.
I have added drag and drop and gestures.
Edgar, are you in?
You put your left foot in, you put your right foot out, you do the hokey pokey and you shake your self about. That's what it's all about.
Just so you know, my library already meets about half to two thirds of those elements listed on your design doc...
IDK... Can we co-develop? Ie. contribute to both code bases at once maybe at times? I don't really want to abandon EAGLE...
No, the Skin class would not need to be subclassed. It's a resource manager. Each widget will know how to get resources from it and apply it to its painting algorithm.
With this technique, how do you deal with ninepatch backgrounds? Ninepatch is very important for drawing backgrounds. How will you differentiate from a normal resource and a ninepatch resource?
Other silly little things that come to mind: What if a user only wants a 2 state button, and does not want to provide a focus texture, a highlight texture, and a disabled texture. Will this do something like:
If has resource loaded for state, use it, else, use default resource.
I also wanted to note a rare case: In my card game, I have a Widget that renders a bitmap that has some opaque and some transparent areas on top of what is normally rendered and then Widgets are rendered on top of that:
{"name":"608312","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/e\/d\/ed789bc69f8058a6d5941a8c020a6b82.png","w":858,"h":939,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/e\/d\/ed789bc69f8058a6d5941a8c020a6b82"}
Ofcourse the user could just override paint methods to achieve this, but, it is a case where subclassing a widget is needed to paint.
Your method is simpler and easier for 95% of cases, but introduces subclassing in rare cases. That's not a problem, but I wanted to bring that sort of weird corner case to your attention.
That brings another feature to mind:
It would be good to have a visibility clipping mechanism. For example, being able to put a ListBox in a ScrollPanel and have the ListBox only render items visible to the user. In Agui, since scrollable widgets directly take in scroll bars in their constructor this is easy to do, but it would be better to have it generalized.
In terms of buttons, you can have multiple implementations. Default buttons that are entirely based on simple attributes like colors and dimensions and the like. That's all you really need for traditional GUI-style buttons that aren't themselves images. You can have alternative implementations for more customizable rendering. Basically, a good library handles as many reasonable cases for you so that you don't have to do a ton of redundant work for nothing.
In terms of buttons, you can have multiple implementations. Default buttons that are entirely based on simple attributes like colors and dimensions and the like. That's all you really need for traditional GUI-style buttons that aren't themselves images. You can have alternative implementations for more customizable rendering. Basically, a good library handles as many reasonable cases for you so that you don't have to do a ton of redundant work for nothing.
Yeah, I agree. I was overkill-trying to separate logic and presentation 
Oh just thought of another feature I like: resizeToContents in the base widget
(or an interface IResizable if you prefer coding to interfaces).
Can we co-develop? Ie. contribute to both code bases at once maybe at times? I don't really want to abandon EAGLE...
You obviously are not looking for a joined project. I don't want to work on Eagle, it's not up to my coding and design standards, so obviously we are off and I am not going to ask you again about collaboration.
With this technique, how do you deal with ninepatch backgrounds? Ninepatch is very important for drawing backgrounds. How will you differentiate from a normal resource and a ninepatch resource?
The widgets that need ninepatches can query the Skin instance about the bitmap or bitmaps they want and any metrics that come along with them. The Skin class itself can have a configuration data type which represents a ninepatch.
If has resource loaded for state, use it, else, use default resource.
Yeah, absolutely. When you request a resource from Skin, you also pass a default value. If the resource doesn't exist, you get the default value back.
I wanted to bring that sort of weird corner case to your attention.
I do not understand the case. Could you elaborate? what is the actual problem?
It would be good to have a visibility clipping mechanism. For example, being able to put a ListBox in a ScrollPanel and have the ListBox only render items visible to the user.
Yes, absolutely, and this is a top priority. In many games, for example in the one I work now, there is a huge problem of resources for big lists and you have to make miracles in order to cut resources down, due to the framework not supporting clipping properly.
Oh just thought of another feature I like: resizeToContents in the base widget
That would be taken care of in the packing phase of the layout.
The ace of Spades container is weird because you essentially have:
Paint the inner children
Paint the ace
Paint the outer children
Actually, now that I remember how I did it:
I have a class Frame in Agui which allows me to put Widgets in the frame's content panel, and in the frame itself.
So the X, cancel and Okay are Widgets of the frame while the inner ones, scrollbar and options are widgets of the content panel.
In this strange scenario, I had to subclass my Frame so that I can do this painthing:
Paint the content panel
Paint the ace image
Paint the Frame's children
Which, now that I think about it, is a scenario where subclassing is pretty much unavoidable. 
I was wondering, since each Widget has a setSkin method, who calls setSkin? Is it the Gui class that has the current skin and gives it to the widget when it is added?
What happens in the case where the skin of the entire gui were to be changed at runtime. Is this possible in a singe line of code?
I'm thinking of Java's Swing where the look and feel of the entire gui can be dynamically changed very easily.
Which, now that I think about it, is a scenario where subclassing is pretty much unavoidable.
You don't need subclassing. You can do it with multiple widget containers stacked on top of each other.
who calls setSkin?
The programmer.
Is this possible in a singe line of code?
Yes:
myGUI->setSkin(Skin("myskin.txt"));
That's cool!
You obviously are not looking for a joined project. I don't want to work on Eagle, it's not up to my coding and design standards, so obviously we are off and I am not going to ask you again about collaboration.
It's a two way street axilmar. If you expect me to donate any or all of my library or time to the community gui library, it might be nice to have something in return ie... freedom to use code from the new library in Eagle as well. As far as not being up to standards, I did say that a lot of the issues on your list were on my todo list, things that I had planned to do anyway. The fact that you're not even willing to discuss my methods suggests you are not a team player. Why would I want to work on a team with you? What do I get out of it?
And what kind of license do you want this library to have?
The fact that you're not even willing to discuss my methods suggests you are not a team player.
I am willing to discuss them. Which one would you like to discuss?
And what kind of license do you want this library to have?
An open source one, of course.
I am willing to discuss them. Which one would you like to discuss?
Well for one, the gui needs to communicate within itself. Which method do you prefer among these or another? 1) WidgetMessages passed from child to parent 2) Listeners 3) Signals and Slots 4) other.
Now explain why and how you plan to handle this in the proposed gui.
Well for one, the gui needs to communicate within itself. Which method do you prefer among these or another? 1) WidgetMessages passed from child to parent 2) Listeners 3) Signals and Slots 4) other.
I prefer the event handler pattern:
a base class named 'EventHandler' contains a method 'virtual void handleEvent(const EventPtr &event)' that allows it to handle incoming events.
a class named 'EventDispatcher' that is derived from class 'EventHandler' allows external classes to attach event handling functions to an object.
a class named 'DisplayObjectContainer' that is derived from class 'EventDispatcher' propagates GUI events from parent to children.
I.e.:
The above design has all the advantages of widget messages, listeners and signals and slots, and more:
it allows messages to be passed from one widget to another or from an external object to a widget.
it provides a listener interface.
the listener interface works as a signal and slot mechanism, since external objects can attach listeners to objects.
if the event is a GUI event, then it allows the creation of modal widgets without a modal loop since widgets lower in the hierarchy can block events of widgets higher in the hierarchy without the addition of special panels.
it allows for propagating down and bubbling up of events: a display object container can choose not to propagate an event to its children or process the event after the children have processed the event.
EDIT: fixed inheritance of EventDispatcher from EventHandler.
I guess class EventDispatcher in your code snipped should inherit from EventHander?
EventListenerId addEventListener(EventType eventType, const std::function<void(const EventPtr &)>);
Don't you need to use mem_function? I never could get the hang of that.
It looks like an interesting idea. Maybe there is some redundancy in my design then, because right now I have both widget messages and listeners.
edit this is what I have right now
void WidgetBase::RaiseEvent(WidgetMsg msg) { // signal your slots PrivateRaiseEvent(msg); // send event to listeners EagleEvent e = MakeEagleEvent(msg); EmitEvent(e); // tell our parent if (wparent) { wparent->QueueUserMessage(msg); } }
Don't you need to use mem_function? I never could get the hang of that.
Not in c++11.
Maybe there is some redundancy in my design then
No shit!!!! :-)
I suppose now you are going to go off and change Eagle5 with this design, aren't you?
No, and you're not doing anything all that original anyway. What you're doing is standard SWING design from java anyway. And yes I might like to reduce my messaging system to perhaps just listeners, and that would be completely within my rights to choose to do so. Stop implying that I just copy peoples work and ideas. It's pissing me off.
No, and you're not doing anything all that original anyway.
I didn't imply that my ideas are original. Hardly anything is original these days.
And yes I might like to reduce my messaging system to perhaps just listeners, and that would be completely within my rights to choose to do so. Stop implying that I just copy peoples work and ideas. It's pissing me off.
So asking another person about design ideas in the context of collaboration and then running off to implement these ideas on their own isn't something to be pissed off at?
Is that good behavior Edgar? I think not.
You clearly didn't think to apply the design I propose to your library, so when you distribute it, it must give me some credit, that being the least you can do.
Unless you still want to collaborate.
Unless you still want to collaborate.
Why would he want to? You've been behaving like complete asshole for some time now.
Why would he want to? You've been behaving like complete ḁsshole for some time now.
I have to also agree. While you may mean well, text can be emotionally ambiguous, so it is important to ensure that you minimize this ambiguity.
You seem to really know your stuff when it comes to programming, but people will be hesitant to collaborate if they get a feeling of hostility. Saying something like: no shiṭ, while in the way you mean it might be nonchalant, without the context of your tone and facial expression, it's generally perceived as the demeaning form "duh, you stupid idiot".
Sometimes it helps to try to read back what you have written to someone as if you were receiving it.
Hopefully, keeping this in mind will allow communication that is more neutral, and that does not in any way make others feel bad, as can happen with the emotional ambiguity of text.
Also you do not own ideas. You said yourself those ideas aren't original anyway. It is entirely his choice to "credit" you with helping him. Just as it's entirely your choice to be helpful or not. I'd say your general attitude robs you of any due credit though. It's clear you aren't helping to be helpful, but doing so in hopes of exploiting him for personal gain. Which is a really shitty attitude. You should just try to help to be helpful or GTFO. If he ends up developing a better library as a result of your discussion then great! Especially if he releases it open source so you can use it to. Nothing stops you from doing the same! Put your egos aside already. Jesus. You both suck or you'd have done this already.
In the previous discussion we had about GUIs, although the technical points I raised were valid, and my behavior was nice, I was mostly ignored.
so I decided to change tactic to make people actually listen to me, because it seems raising technical points it's not enough, and being nice is also not enough.
My apologies to anyone that was insulted, that wasn't my intention.
EDIT:
Also you do not own ideas. You said yourself those ideas aren't original anyway. It is entirely his choice to "credit" you with helping him. Just as it's entirely your choice to be helpful or not. I'd say your general attitude robs you of any due credit though. It's clear you aren't helping to be helpful, but doing so in hopes of exploiting him for personal gain. Which is a really attitude. You should just try to help to be helpful or GTFO. If he ends up developing a better library as a result of your discussion then great! Especially if he releases it open source so you can use it to. Nothing stops you from doing the same! Put your egos aside already. Jesus. You both suck or you'd have done this already.

Just saw the above.
Well...I really don't have an attitude. I wouldn't expect people to be so emotional.
What I really want to see is collaboration. Doing an enormous project like a GUI by myself is not fun.
It's also very illogical for many people to work individually on a GUI, when they could collaborate. The spending of resources is illogical.
If I didn't want to collaborate, I wouldn't discuss designs, I'd have completed my library by now.
I thought the whole point of collaboration was for both parties to benefit. :/
I do like your idea though. I think it would work well.
As far as me using it in my library goes, not likely. My QueueUserMessage system works just fine for now, and I see no point to refactor that too just yet. I need to just sit down and work on my layout managers and then start porting widgets. What should the default layout of a container be? An expander? Ie., it takes up the full space of the panel it is on?
JPanel uses a FlowLayout... to do as your suggesting, perhaps BorderLayout where north,south,east,west have nothing?
What should the default layout of a container be?
I don't think a container should have a default layout. When building a hierarchy of containers, it is seldom that a default layout can be useful. In most instantiations of a container, a different layout is instantiated.
I usually set up layouts with a dedicated layout widget. A top level or group widget would just be an open free form area, and if you want a layout, you use a hbox, vbox, table, splitter or another type of layout widget.
Another options is a non widget layout object that you attach to containers. But I find its easy enough to just make them child widgets.
Making layouts be widgets makes the reuse of layout algorithms more difficult than they can be.
For example, a window frame does not have a specific layout. Forcing it to have a specific layout makes changing layouts of the frame more difficult thab it can be: you either have to subclass the window frame to change its layout or add a container to it with the desired layout, which means one more widget consuming resources unneccesserily (the window frame could have the layout the container has).
Plus ot hardcoding the layout on a widget makes the whole thing a lot more flexible, for example the orientation of a scroll bar could change by simply altering the layout of its root widget, whereas with hardcoded layout the scrollbar needs a different base class for each orientation.
Yeah, but how often that happens, especially in games, I don't think it really matters in most cases.
Yeah, but how often that happens, especially in games, I don't think it really matters in most cases.
Many many times. In the current game I work, I had to implement the layout system in that way, because the same problem kept coming up over and over.
Maybe you're doing it wrong
jk.
Not really. It has increased the code reuse and simplified the code.
Plus ot hardcoding the layout on a widget makes the whole thing a lot more flexible, for example the orientation of a scroll bar could change by simply altering the layout of its root widget, whereas with hardcoded layout the scrollbar needs a different base class for each orientation.
I don't think you could switch from a h to a v scroll bar just with a layout change. You also need to change the bitmaps orientation or change the image so the buttons would work. What I would do is have an hscrollbar and a vscrollbar (instantiate both) and then only have one visible at a time.
Making layouts be widgets makes the reuse of layout algorithms more difficult than they can be.
I really don't think so. I have widgets be layouts so they can be nested inside each other, because a layout holds widgets, not layouts and widgets separately. One layout can hold another directly as if it were a widget. All the widgets are registered separately to the gui. The layout object is strictly in charge of positioning (and/or resizing) widgets.
edit
Ie. you don't need panels, because layouts provide their functionality (but you can still have one if you need one). Saves resources by not having multiple buffers.
I don't think you could switch from a h to a v scroll bar just with a layout change. You also need to change the bitmaps orientation or change the image so the buttons would work. What I would do is have an hscrollbar and a vscrollbar (instantiate both) and then only have one visible at a time.
In the game I work, the scroll bar class I have created has an orientation property. If I set the orientation to horizontal, I also change the layout to horizontal, if I set the orientation to vertical, I change the layout to vertical.
Then subclasses of the scroll bar that implement the actual components can choose the actual graphics from the 'orientationChanged' event.
I have widgets be layouts so they can be nested inside each other, because a layout holds widgets, not layouts and widgets separately.
By having separate layouts, you can do that too. In my GUI library for the current game I work at, each widget has a pointer to a layout object, and layout objects can be shared with widgets. I have a set of functions that create horizontal boxes, vertical boxes, grid boxes, etc, and all these share the same layout instances. I also have layout instances that need parameters, and for these each widget has its own layout instance.
The advantages of separating layouts from widgets are:
less widget instances. If a container has a hardcoded layout, then in order to change that layout you may add another widget to it with the appropriate layout.
less subclassing. If a container has a hardcoded layout, then in order to change that layout you may subclass it.
less resources. If layout instances can be shared across objects, then that means fewer application resources.
For example, suppose you have a button with a horizontal orientation, which puts a text and an image side by side.
Suppose the button's layout is hardcoded because it inherits from class HBox.
In order to reuse the button code with a vertical layout that puts the image above the text, you have the following options:
1) create a new instance of VBox, put it inside the button, then add the image and the text in the vbox.
2) subclass the button to modify its layout algorithm internally. Then you break the contract that the button inherits from HBox.
If the layout is not hardcoded in the button, then all you have to do is change its layout.
Furthermore, if layouts are separated from widgets, writing new layout classes is easier: in the new layout class you don't have to deal with all the details of widgets. If layouts are hardcoded in widgets, creating a new layout means creating a new widget instance, providing constructors (if needed) for the base class that have to deal with widget properties that are unrelated to the actual layout, etc.
Additionally, debugging code in which layouts are separated from widgets is easier: if you have a problem with layouts, then you simply look at the layout code. You don't have to deal with all the rest of the widget code.
In the game I work, the scroll bar class I have created has an orientation property. If I set the orientation to horizontal, I also change the layout to horizontal, if I set the orientation to vertical, I change the layout to vertical.
In my library, a widget can have any layout it wants, as well as use its own to position its children if it wishes. Each widget is 'owned' by one or zero layouts and managed by a single widget handler.
I don't know why you would ever make a widget inherit from a layout class.
I have widgets be layouts
Correction - I have layouts be widgets so they can be nested. Said that backwards.
If a container has a hardcoded layout
In my engine the user creates a layout, makes all its sublayouts and connects them, and then that layout is registered with the widget handler layout component which simply expands the object to the full size of the container. You can use whatever layouts you want with it.
I could also make the widget handler own a pointer to a layout in which case I would just have the widget handler resize the layout whenever it was resized.
In any case, for most intents and purposes, my layouts are separate from widgets. They inherit from WidgetBase merely to allow layouts to hold layouts as widget pointers.
If I may, one of the things that I find really helpful with design is putting implementation details aside and coming up with a stateless API. Which is to say, your base classes have no defined state (i.e., data). What methods must they have to get the job done, and what pieces of data and code (more interfaces, which is essentially also "data") need to be fed into them for them to accomplish their intended purpose?
Inheritance is a tricky tool to wield, but it will help a lot if you figure out the purely virtual interfaces for your objects. Your implementation classes (base classes and derived classes) won't inherit any state or code from your interface classes. The only thing the interface classes do is provide a defined way of interacting with an object whose state is completely abstract.
It is best if you can use your objects through these interfaces instead of directly through base or derived classes with known implementation details. Just a thought... I know that coming up with "interfaces" before implementations results in much better designs for me.
My design is a lot simpler than your design Edgar. And my base layout class is stateless.
And in my case I have the advantage that a layout has all the background features of a widget, such as its outer and inner area as well as its background, margins and 9 patch area. You can give your layouts a border just as if they were a separate panel as well as a background, which are all drawn automatically when WidgetBase::Display is called which is auto called by the gui.
I think the main difference here is that I have something mostly working and all you have right now are design ideas. Last time I looked at algui all you had was component and container, and all they did was hold components.
And in my case I have the advantage that a layout has all the background features of a widget, such as its outer and inner area as well as its background, margins and 9 patch area. You can give your layouts a border just as if they were a separate panel as well as a background, which are all drawn automatically when WidgetBase::Display is called which is auto called by the gui.
Not an advantage, more like bloatware.
I can achieve the exact same functionality by combining a tiles bitmap and a frame layout.
I think the main difference here is that I have something mostly working and all you have right now are design ideas. Last time I looked at algui all you had was component and container, and all they did was hold components.
All that I am describing are actually implemented in the gui of a big commercial mmo that I work on.They are on the market, tried and tested.
All that I am describing are actually implemented in the gui of a big commercial mmo that I work on.They are on the market, tried and tested.
Which is proprietary, and very unuseful to anyone like us. Do they ever plan on making it open source? Probably not, it's their moneymaker.
Obviously you have your own ideas and you don't care for anyone elses. Fine. That's why we have 10 different guis. I don't see myself abandoning what is already mostly working for something totally unwritten to work on a project with someone who refuses to see merit in any design other than his own. You want to be a project leader? Go ahead. But don't expect me to donate any of my time to your project.
And you have your design now, so why don't you go code it then. If it is so much simpler and easier to do it your way then you should be done in no time at all. 
edit
And those are features common to almost every widget. A widget should be able to have a border or margins and a 9 patch background that resizes automatically as they do. And you can leave any or all of it blank and it will not be drawn. It's a feature, not bloat.
Which is proprietary, and very unuseful to anyone like us. Do they ever plan on making it open source? Probably not, it's their moneymaker.
That's not the point. The point is if my ideas are implemented anywhere, and yes, they are implemented.
Obviously you have your own ideas and you don't care for anyone elses. Fine. That's why we have 10 different guis. I don't see myself abandoning what is already mostly working for something totally unwritten to work on a project with someone who refuses to see merit in any design other than his own. You want to be a project leader? Go ahead. But don't expect me to donate any of my time to your project.
Actually I am not refusing to see merit on your design, I am simply rejecting it in favor of a better design. My design has more advantages than yours, plainly and simply, in this area (in another area your design might have more advantages than mine, and so I'd choose your design over mine).
And you have your design now, so why don't you go code it then. If it is so much simpler and easier to do it your way then you should be done in no time at all
I've already done it for my job, I am too tired and bored to go ahead and write another gui toolkit on my own.
And those are features common to almost every widget. A widget should be able to have a border or margins and a 9 patch background that resizes automatically as they do. And you can leave any or all of it blank and it will not be drawn. It's a feature, not bloat.
Nope. Only some widgets have those features, not all widgets.
EDIT:
Your problem is your ego, actually: you think that your choices are the best, without sitting down and thinking about if they are truly the best.
And no, I do not have the same problem, because what I do is present a list of arguments that support my design, compare them to the list of arguments for your design and find my design better.
And I am admitting that this concerns only specific parts of a GUI library that I have experience on.
If you come up with a better design, then I'd gladly adopt it, something you will not do.
And thus 10 different gui libraries for allegro are born.
There isn't just one perfect way to do everything axilmar. I expected someone of your age would know that by now.
No, I'm not going to implement your ideas, what I have works for now. If it ain't broke don't fix it. You're welcome to implement your own. And if and when you have something comparable to what I have spent the last 5 years working on then we'll talk.
Edit
----
Your problem is your ego, actually: you think that your choices are the best, without sitting down and thinking about if they are truly the best.
I never said my ideas were best. I am saying its not worth it for me to re-implement something I have already done another way that is perfectly suitable already.
I've already done it for my job, I am too tired and bored to go ahead and write another gui toolkit on my own.
Why should I abandon what I have to start all over with you? That's a serious investment of time to make for something that is still in design stages. My system is nearly complete. What do I get out of this? You say you have the experience to do it, so it should be a relatively simple matter for you to reimplement what you have done already. What do you need my help for? You know everything already, according to you.
Your system is nearly complete? You don't even have a single widget yet.
If you don't want to cooperate, that's just fine with me. But don't you ever again say why do we have so many different guis.
Actually, I believe Eagle has several widgets, at least this image depicts this:
{"name":"EagleScreenie.png","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/5\/8\/585af629d1ee20e7211741423b70fad0.jpg","w":812,"h":632,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/5\/8\/585af629d1ee20e7211741423b70fad0"}
Maybe they just have not been ported from the Allegro 4 version, but that would not be too hard to do... I would think.
There's valuable discussion going on here, let's not get derailed.
Finish the design doc and everybody can implement what parts they want and/or keep their own projects.
I don't think either of you guys has explained in enough in detail why your layout management system is
(better, easier, more flexible) than the other guys.
I'd be amazed if this hasn't been discussed ad-nauseum somewhere else.
How about a link to some other gui layout system that works similarly to what you want to implement.
Meanwhile discuss an interface for the layout system and come back to the details later:
widget->setOrientation(int type);
anything else 
Meanwhile let's move on.
Returning to the design doc:
============================
Question about this:
“proper clipping; ignore widgets that do not intersect with the clipping rectangle defined by the hierarchy of widgets.”
-you mean ignore rendering of widgets outside parent clip boundary or input also?
-to be clear you're talking about view-clipping and not tracking changes/damage to gui.
widget-rendering:
============================
Requested Features:
-ability to override/disable rendering for a widget (without sub-classing?), without affecting child widgets. Children will be rendered normally.
-separate processing gui layout from the actual rendering.
I should be able to let the GUI do everything (layout+input management) for me and
I can still draw all the widgets myself if I so choose.
-widget->RenderOver : eg: over-hanging tabs
-widget->RenderUnder: eg: drop-shadows
Let's discuss render-backend:
============================
Support multiple render methods:
Eg:
1. SimpleRender – painter's algorithm (Render widgets back to front).
CONS: Slow
PROS: easy to implement when:
a) adding a new back-end (this is phase #1)
b) performance doesn't matter
c) no support for buffering (legacy / embedded / low-memory /
)
2. CacheRender -
TODO: We haven't discussed tracking damages/changes for redrawing widgets
How to handle transparency/translucency?
-do you need to query what features are available?
-allow switching between render methods?
Should this be a class/interface?
Maybe they just have not been ported from the Allegro 4 version, but that would not be too hard to do... I would think.
Yes, just a matter of replacing some drawing calls and updating a few functions to match the new specs. But still I haven't had time for it yet. I have to update BITMAP* to EagleImage* too. I also have to replace Update and CheckInputs to use EagleEvent's. So there is a decent amount of work to be done yet.
Your system is nearly complete? You don't even have a single widget yet.
Eagle4 is functional, but again, it depends on Allegro 4. It has lots of widgets, like button, bitmap viewer, camera, drop down list, scroll bars and buttons, icon button, list box, menu item and menu and menu bar, radio button, slider, tab and tab group. There is a file selection dialog and a gfx mode selection dialog. But, it has to be ported.
Eagle4 is functional, but again, it depends on Allegro 4. It has lots of widgets, like button, bitmap viewer, camera, drop down list, scroll bars and buttons, icon button, list box, menu item and menu and menu bar, radio button, slider, tab and tab group. There is a file selection dialog and a gfx mode selection dialog. But, it has to be ported.
Oh, ok, I didn't see any widget code in the svn repository.
Well, if your system is nearly complete, then you don't need any help, do you? the discussion is pointless then, when it comes to a unified Allegro gui system.
Oh, ok, I didn't see any widget code in the svn repository.
I told you earlier it was in a different repo :
svn checkout "svn://svn.code.sf.net/p/eaglegui/code/trunk eaglegui-code"
My system is hardly complete, but its got all the pieces there alright. The system and events and input and drawing are all there but the gui pieces haven't been assembled yet, so their design is subject to modification. If there's anything I am interested in it is widget design and I know I could probably simplify a lot of my code, but I think my menus are that complex just because they are complex to begin with.
Anyway, I'm all for discussion.
edit
I think you think I should turn my library into what your idea of a library should be. That seems silly, and too much refactoring. Also the idea of starting over from nothing is silly and a complete waste of my collected gui work. So we're at somewhat of an impasse.
I don't mind contributing code and possible design discussion, but I don't want to be a full contributor. I already have one library to look after...
Well, ok. I work full time anyway, so if you complete your library, kudos to you. As I said earlier, I am too bored to do it alone.
I didn't speak for a complete rewrite, of course, if we were to start over we'd bring the good parts of Eagle5 onto this library.
Edit: by the way, there are lots of other libraries we could use. For example:
http://sourceforge.net/projects/my-gui/?source=directory
Another nicer one:
http://static.cegui.org.uk/docs/current/
Edit2: wow, CEGUI is complex!!! why do they make such software...a gui library is a simple concept, it need not be so complex!!!
One major reason I think we have over 10+ guis is the following. Most people's motivation is to make a game, not a gui. But to make their game, they need a gui. They are therefore motivated to make a gui that will help them make their game.
If people are blindly contributing to a gui api, without any personal gain (eg, be able to use it in their own game) motivation significantly decreases.
This is probably also why we do not see many game engines. Good game engines should not really have a specific purpose, but without a specific purpose, motivation probably decreases after the first few weeks.
My motivation behind agui was for my card game, but I also hoped it could be useful for others so I made it backend independent and open source. Had my mindset been: I want to make 1 great gui that will satisfy all gui needs for no particular purpose, I would have probably not made it past a button.
I think this is also why there is nothing out there comparable to QT that is free and open source. Generally if people are motivated enough to complete a gui api, it will serve the purpose of being used in their software or it will be proprietary and sold.
That's how I see it.
A GUI is complex. You can certainly limit the scope of it, but you will be limiting its functionality. That will make it more suitable for some purposes, and less suitable for others. You need to fully define what purposes it should be suitable for to do that. "Games" is not defined.
Personally, my motivation is quality software. I'd like to see a good gui library that will help all of us quickly create guis and with as few bugs as possible.
This reminds me a lot of an open source game called Wesnoth I contribute to. They started replacing their GUI system about 5 years ago because their original GUI code was just hacked together.
However despite a lot of continuous work on it the new GUI (called GUI2) still is nowhere near done and they are not using it yet. The source looks like this: [1]
I sometimes wonder if they will ever get to use it. I'm pretty sure they originally thought it would at most take a year or so to implement a simple GUI. And theirs also is designed specifically for one single game with no intention to ever use it for something else, so something much easier than a general one...
Ok, say I want to use one of the GUIs kindly made available by people here before I spend weekends/months rolling my own. Wouldn't it be nice to agree on a (not too) simple example use case to see how that could be achieved with the different GUIs people have made here? I'd like to see some code, how to actually use the GUIs, in comparison. I can't think of a good example right now, though. Maybe that's the problem, as everyone here has different requirements. But it all comes down to the user pressing some buttons after all.
My goal with my library is to provide the ease of gui programming with Java inside a C++ environment. And to make better built in layout managers than what Java provides, because they lack a lot of features. The one feature that they totally needed was a pin layout, where you specify coordinates from 0 to 1 and widths from 0 to 1. All relative to the container they are in. Or how FlowLayout needs a vertical alignment component, and how you need to be able to have empty places in a GridLayout without using invisible widgets. That sucks.
What is a good compiler to aim to support now? mingw32-gcc 4.7 and 4.8 support -std=c++11 and -std=gnu++11 and the latest version of mingw binaries for allegro is 4.7. To be honest I never really learned all the new features of C++ 11.
that they totally needed was a pin layout, where you specify coordinates from 0 to 1 and widths from 0 to 1
Is that really needed? I mean, is there a use case where the contents of a container must scale uniformly? I have never seen such a case in all these years.
I think I would find it handy at least. And it is simple enough to provide it anyway. And my GridLayout is going to support per cell horizontal and vertical alignment. As well as allowing cells to span multiple columns or rows like Java's GridBagLayout.
Personally, I do not really see the need for cell horizontal and vertical alignment or a pin layout. So far every case of layout I have seen is covered by the following layouts: flexible, center, stack, grid, box (either horizontal or vertical).
For example, in order to achieve left-center alignment in a grid cell, I'd create a horizontal box with a centering box that includes the desired widget and a flexible box to push the centering box to the left.
For spanning multiple columns or rows I'd create a simple layout which simply drags the bottom left-corner of a widget to its own bottom left corner.
From experience I've seen that lego-like composition is nicer than programming specific features, if it can be avoided.
Why not use CSS for layout?
Isn't CSS a bit too much to make a library of? it needs a parser, doesn't? also, doesn't it need a DOM or something similar?
Complicated or not: wouldn't a CSS layout manager just be another layout container widget?
wouldn't a CSS layout manager just be another layout container widget?
Actually no. A CSS document contains style instructions for a whole GUI (or HTML document). It's more like a skin.
For example, in order to achieve left-center alignment in a grid cell, I'd create a horizontal box with a centering box that includes the desired widget and a flexible box to push the centering box to the left.
What? Managing an invisible widget for the sake of alignment? That sounds like having to use invisible widgets as placeholders in Java's GridLayout. That sounds like a bad idea.
For spanning multiple columns or rows I'd create a simple layout which simply drags the bottom left-corner of a widget to its own bottom left corner.
Why not just give it a cell x,y,w, and h?
Personally, I think that rather than looking for pixel-perfect GUIs we should seek fully dynamic GUIs that Just Work(tm). I'd prefer a GUI with zero coordinates or widths/heights. Something that just magically made everything flow together no matter how you resized things, etc. I only briefly worked with Qt tutorials, but I was quite pleased with the layout widgets that effectively did this for you. I'm sure that gets bastardized with fixed coordinates and dimensions, but it seems possible at least to leave that stuff out of the picture. You probably shouldn't want empty space in your UI. And when there has to be empty space, you should let the UI API figure out how to use it appropriately with subtle hints in the programming. The positioning and sizing should all be dynamic, IMO.
What? Managing an invisible widget for the sake of alignment? That sounds like having to use invisible widgets as placeholders in Java's GridLayout. That sounds like a bad idea.
It's a great idea. You can create very complex guis very easily, even with one liners.
Actually, it's not an idea, it's the way DFUW's J2F framework works. It has an existing implementation.
Why not just give it a cell x,y,w, and h?
Because a cell is redundant in this case.
Imagine having a grid of 10000x10 items, for example: if you have one cell object per cell, then you'll have 100,000 objects.
And if you think that 10000x10 is a rare case, it is not. Many games need that, to present long lists of items (market, leaderboards, achievements, etc).
Something that just magically made everything flow together no matter how you resized things, etc.
That's exactly what I am talking about.
In DFUW's new GUI system, the position and sizes of widgets is never specified. It's always computed automatically from the layouts.
For example, the chat window of DFUW is made entirely out of layouts:
http://www.youtube.com/watch?v=jU4ulaqYZfA
Take a minute to watch the video, it's pretty interesting: the chat window contains several popups, one of them being the chat options, which is quite complex: it has radio buttons, check boxes, labels, text boxes with custom backgrounds, accept and reject buttons, a dynamic list box, a scroll bar etc.
It's all made with layouts.
And if you play Darkfall and you switch languages, the chat window and its popups all automatically adjust themselves to the size of the fonts used in other languages.
It's a great idea. You can create very complex guis very easily, even with one liners.
Not really. You have to manage your invisible widget sizes then, and adjust them to make sure they are creating the proper alignment. And being able to cram everything into one line is not a feature and hurts readability.
Imagine having a grid of 10000x10 items, for example: if you have one cell object per cell, then you'll have 100,000 objects.
You only need one object per actually occupied cell. Without using a cell parameter you can't leave spaces in the grid. There's nothing wrong with a grid holding a cell. And you can differentiate between a regular grid class and the flexible grid class. No reason they have to be the same.
struct GRIDCELL {int x,y,w,h;WidgetBase* widget;}
At 5X4X10000 that's only 200,000 bytes. That's 200k of memory. Not worried about it.
It's always computed automatically from the layouts.
That's the same way my layouts will work. Add a widget to a layout and the layout positions and sizes it. Move the layout and the widget is updated.
For example, the chat window of DFUW is made entirely out of layouts:
I don't think I understand how you want to implement layouts. Example code? Pseudo code?
Not really. You have to manage your invisible widget sizes then, and adjust them to make sure they are creating the proper alignment.
Nope. The size and position of these widgets is automatically calculated.
And being able to cram everything into one line is not a feature and hurts readability.
Nope. For example, you can write
Row(center(textbox()), left(stack(button(),bitmap())))
Which is extremely readable.
At 5X4X10000 that's only 200,000 bytes. That's 200k of memory. Not worried about it.
Nope. In my example, the grid had 10000 rows by 10 columns. That's 100000 grid cell instances.
If you allocate them with a single array, then they take 2 mb. Nice way to increase the cache misses in the 1st level cache and dramatically reduce the performance of your game.
For smaller devices, 2 mb ram is significant.
If you do not allocate these entries as a single array, then you risk memory fragmentation. You may alleviate this by using a memory pool though, but then you have the risk of memory management.
The pointer to the widget base is also a raw pointer, not a shared pointer. If you make it a shared pointer as you should, then we are talking about 4 more bytes per grid cell.
That's the same way my layouts will work. Add a widget to a layout and the layout positions and sizes it. Move the layout and the widget is updated.
Of course, we would not talk about automating positioning and sizing with layouts if that wasn't automatic.
I don't think I understand how you want to implement layouts. Example code? Pseudo code?
Did you watch the video? I am asking you because I can explain it to you using concrete examples.
Qt's Designer had these spacer "widgets" you could place to manage some spacing. But they really weren't widgets, I think they were actually just layout children, rather than full fledged widgets, and played with the properties of that layout child cell.
If you allocate them with a single array, then they take 2 mb. Nice way to increase the cache misses in the 1st level cache and dramatically reduce the performance of your game.
The entire 2mb won't be used at the same time. The L1 cache can more than hold the visible elements in a grid.
For smaller devices, 2 mb ram is significant.
When will you be using a grid with 100,000 elements on a smaller device? Or even at all?
Nope. For example, you can write
Row(center(textbox()), left(stack(button(),bitmap())))
Which is extremely readable.
Not with your example of ten elements in a row. That would become an unreadable nightmare quickly unless you broke each element onto its own line. Does your Row use tuples? I'm only asking b/c it seems like it would have to.
Here is what I would have :
grid.setElement(row , 1 , textbox , HALIGN_CENTER); grid.setElement(row , 2 , iconbutton , HALIGN_LEFT);
Very readable, and no extra layout objects are necessary.
What I don't see is how you achieve your nested layouts. Do all your widgets and layouts derive from a common base class?
The pointer to the widget base is also a raw pointer, not a shared pointer. If you make it a shared pointer as you should
It is not necessary to use shared pointers for widgets in my gui. When you add an element to a gui you tell it whether to destroy the widget when done with it (ie. when removed from the gui). I use a simple map<WidgetBase* , bool> to track which widgets need to be destroyed. And how would a shared_ptr work with a statically allocated widget?
Did you watch the video? I am asking you because I can explain it to you using concrete examples.
I watched part of it, about the first half. I didn't see anything extraordinary in terms of layout really. What specifically did you want me to see? The second half didn't have much in the way of gui.
The entire 2mb won't be used at the same time. The L1 cache can more than hold the visible elements in a grid.
The problem is not that the L1 cache cannot hold all the visible elements in the grid, the problem is that it will push other things out of the cache.
When will you be using a grid with 100,000 elements on a smaller device? Or even at all?
Lots of games have requirements for big lists. It's better to be proactive than reactive.
Very readable, and no extra layout objects are necessary.
No one is forcing you to write everything in one line. You could always write it like this (real life example):
SFSpacer row = SFSpacer.createHBox(); row.addChild(SFSpacer.createCenter(new SFBitmap("IconFeatBitmap"))); row.addChild(SFSpacer.createCenter(_createSelectedFeatCurrentPointsText())); row.addChild(SFSpacer.createCenter(_createSelectedFeatTotalProgressText())); row.addChild(SFSpacer.createFixed(16, 1)); row.addChild(SFSpacer.createCenter(new SFBitmap("IconProwessBitmap"))); row.addChild(SFSpacer.createCenter(_createSelectedFeatCurrentProwessText())); row.addChild(SFSpacer.createCenter(_createSelectedFeatTotalProwessText())); row.addChild(SFSpacer.createFlexible()); return row;
What I don't see is how you achieve your nested layouts. Do all your widgets and layouts derive from a common base class?
It's simple: each widget has a pointer to a layout instance. The layout instance takes care of managing the widget's size, if it depends on its children, and the position and size of children.
It is not necessary to use shared pointers for widgets in my gui.
Wrong approach. When you need to hold widget references from different places, your approach will come to make your life difficult.
And don't tell me that you don't need to hold widget references from different places, because you do. You often have to update part of a complex widget that lives in another container than the current one, so instead of querying each time the container you hold a reference to the child.
And how would a shared_ptr work with a statically allocated widget?
Use an empty deleter.
I didn't see anything extraordinary in terms of layout really.
It depends on what you mean by extraordinary. The whole gui is created with few primitives, using aggregation. That's 'extraordinary' in terms of programming elegance.
The problem is not that the L1 cache cannot hold all the visible elements in the grid, the problem is that it will push other things out of the cache.
Lots of games have requirements for big lists. It's better to be proactive than reactive.
Sure you're not being premature in your quest to optimize?
It's simple: each widget has a pointer to a layout instance. The layout instance takes care of managing the widget's size, if it depends on its children, and the position and size of children.
This is the same as in my gui. The only difference is that I allow a layout to act as a panel and widget.
Wrong approach. When you need to hold widget references from different places, your approach will come to make your life difficult.
And don't tell me that you don't need to hold widget references from different places, because you do. You often have to update part of a complex widget that lives in another container than the current one, so instead of querying each time the container you hold a reference to the child.
And how would a shared_ptr work with a statically allocated widget?
Use an empty deleter.
I haven't come across the situation where any widget needs to know about another widget that it isn't directly responsible for to begin with. You don't need a shared pointer to reference a widget. If something depends on a certain widget not being destroyed then don't destroy it until you're done using it. I understand shared_ptr can automate that, but I honestly haven't come across any situations where it would make my life substantially easier.
Also, how would an empty deleter work? Are shared_ptr's type compatible across different deleters? Ie, how could you use a shared pointer to a stack object with shared pointers that have been set up to delete their object when done?
It depends on what you mean by extraordinary. The whole gui is created with few primitives, using aggregation. That's 'extraordinary' in terms of programming elegance.
Well it sounds good enough. I would like to see their code though. Is it open source?
Also, how would an empty deleter work? Are shared_ptr's type compatible across different deleters? Ie, how could you use a shared pointer to a stack object with shared pointers that have been set up to delete their object when done?
A deleter is just a function or functor that is supposed to destroy the object passed in when invoked. An empty deleter would just be an empty function so that when invoked it does nothing:
I believe that Boost defines an empty deleter, but I'm not sure that the C++11x standard includes one...
Yes, but is a shared pointer with an empty deleter compatible with a shared pointer with a non empty deleter? Ie can they be used together? Can you use a shared pointer to a stack object in a list of shared pointers to heap objects?
Of course. The deleter is a run-time thing. Each instance of a shared pointer has its own deleter.
If you have to specify the deleter, how is that different from me specifying whether or not to delete my widgets when done? I understand a shared pointer tracks the number of references to an object, but in my case only one class is responsible for destroying widgets and that is the layout. When you remove a widget from a layout it uses its stored bool value to determine whether to destroy it or not. Maybe there are better ways, but this is what I have right now.
In your library you might not benefit much. A single place to destroy widgets is pretty easy to get right, or fix bugs at. One advantage of smart pointers would be that the decision to keep or destroy is automatic, and can change more easily at any time. For example, a remove() method could remove a child widget and return a smart pointer. If that is the last reference and the user doesn't hold onto it the widget will be automatically destroyed. If the user holds onto it or references exist elsewhere the widget will remain alive. All automatically. The programmer doesn't even have to think about it.
Sure you're not being premature in your quest to optimize?
I am not. If you don't design it properly from the get go, then you'll create a mess afterwards. Things like that optimization cannot be done properly if not done from the beginning.
This is the same as in my gui. The only difference is that I allow a layout to act as a panel and widget.
So not the same at all.
I haven't come across the situation where any widget needs to know about another widget that it isn't directly responsible for to begin with.
Believe me, the need arises more often than you can imagine. Especially if you have a deep tree of widgets, due to the existence of layout widgets, you will need to keep pointers to the interesting widgets in your main window.
Also, how would an empty deleter work? Are shared_ptr's type compatible across different deleters? Ie, how could you use a shared pointer to a stack object with shared pointers that have been set up to delete their object when done?
The deleter is part of the struct that is shared between pointers.
Well it sounds good enough. I would like to see their code though. Is it open source?
Nope.
I believe that Boost defines an empty deleter, but I'm not sure that the C++11x standard includes one...
You don't need one, an empty lambda function will do.
If you have to specify the deleter, how is that different from me specifying whether or not to delete my widgets when done?
When using shared pointers, and assuming you don't have reference cycles, you don't care about when to set the widget for destruction.
In your case, you do. Your design is nothing more than deleting an object with a delay, which doesn't solve any reference problems.
You don't need one, an empty lambda function will do.
Touche. I haven't been using C++11x so I'm not used to having the new features.
Just for your reference, the code name was C++0x but the official name is C++11 and not C++11x
The code name changed to C++1x at some point I think
or at least people started calling it that after 2009.
Just for your reference, the code name was C++0x but the official name is C++11 and not C++11x
Good catch.
I evidently wasn't paying too much attention.
Forget about it, it was Jasper that informed Tomasu, he deserves no cookie
Believe me, the need arises more often than you can imagine. Especially if you have a deep tree of widgets, due to the existence of layout widgets, you will need to keep pointers to the interesting widgets in your main window.
Even if you do need a reference to a widget, leave the deletion of the widget to its owner. If you delete your widget before you're done with it, that's your own problem.
In your case, you do. Your design is nothing more than deleting an object with a delay, which doesn't solve any reference problems.
But my design also doesn't have any reference problems. When the layout with the widgets is on it is destroyed so are the widgets. It's simple to avoid problems, don't destroy your layouts until you're done with them.
I will admit though, I'm having kind of a design quandary. The lines between layout and widget handler are kind of blurred right now. Right now layouts do one thing, and that is position widgets. My widget handler takes care of drawing and input and event handling. The problem is sometimes it would be advantageous to have layouts draw their children but then they have to implement z order, dirty rectangles and / or buffering the gui image.
I just haven't come up with a nice way to keep everything separated out into a nice modular design. What I have works, but its a blurred line as to who should be responsible for drawing.
Even if you do need a reference to a widget, leave the deletion of the widget to its owner. If you delete your widget before you're done with it, that's your own problem.
That's an unnecessary limitation to impose on developers.
By default, yes parents can delete their children.
There's no reason not to be able to set a flag on a widget: DeleteChildWidgetsOnDestroy(bool flag);
eg: you could be dynamically building a listbox.
It's easy to store the ListBoxItem widgets in a collection
and populate the listbox every time it's made visible.
Devs can be referencing widgets in all kinds of ways (eg: as hash keys),
and want them to live beyond the life of their container widget.
Even if you do need a reference to a widget, leave the deletion of the widget to its owner. If you delete your widget before you're done with it, that's your own problem.
Most of the time there isn't a clear owner of a widget. This is especially true when using layout widgets: the layout widgets are never the actual managers of their children widgets in terms of functionality.
But my design also doesn't have any reference problems. When the layout with the widgets is on it is destroyed so are the widgets. It's simple to avoid problems, don't destroy your layouts until you're done with them.
You simply transfer the lifetime management problem of the child widget to the parent layout widget.
In other words, with your design, the question 'when shall I delete this widget?' becomes 'when shall I delete this widget's parent?'.
I just haven't come up with a nice way to keep everything separated out into a nice modular design. What I have works, but its a blurred line as to who should be responsible for drawing.
That's not the only problem of your library, but it's nice to admit at least one flaw of it.
Devs can be referencing widgets in all kinds of ways (eg: as hash keys),
and want them to live beyond the life of their container widget.
Absolutely. It comes up very often.
Well really what I want is more of a widget factory, where the allocated widgets are managed by the system and don't get destroyed until it shuts down or you ask it to destroy a widget prematurely b/c you're done with it. That's the way I have it now, the system owns all windows, and all windows own all images and fonts and none get destroyed until you say you're done with them or you delete the system. That's exactly one point of memory to manage. Ie. when do I delete the system.
I guess we'd need a memory-pool (hierarchical?) with reference counting to accomplish this. Then we can re-use it for shared objects (icons, text, etc.)
Depends how much hand-holding vs performance we want to trade.
I really like Enlightenment E18 and their Eo object model.
They even go so far as to hide object pointers from you completely.
All you get is an object id to interact with.
Well really what I want is more of a widget factory, where the allocated widgets are managed by the system and don't get destroyed until it shuts down or you ask it to destroy a widget prematurely b/c you're done with it. That's the way I have it now, the system owns all windows, and all windows own all images and fonts and none get destroyed until you say you're done with them or you delete the system. That's exactly one point of memory to manage. Ie. when do I delete the system.
Well, if you use shared pointers then there is NO point of memory to manage. And no point of management beats one point of management every time.
All you get is an object id to interact with.
And the object id becomes the pointer then.
Look guys, there is no need to reinvent the wheel. There is a reason that reference counting was invented. I guarantee you that any other choice you make will not be cleverer and more desirable than what there is already out there.
Let's not forget that thousands of people everyday have to deal with memory & resource management in C++ and if your methods were truly better then they would have been widely adopted.
if your methods were truly better then they would have been widely adopted
Haha
Hmmm, actually I think something like jQuery would be a really neat GUI API. Basically you query the GUI for a particular element or set of elements (using CSS-style selectors) and interact with the results in standard ways with a shared API. If your query doesn't match any elements then all interactions with that query result are basically a NO-OP. So no errors/exceptions if things don't exist. If they do exist then things just work.
Doing something similar for a native GUI would be quite powerful, I think. I know that it makes jQuery super powerful. Of course, if you need an element (i.e., widget) to exist then you can check the results of the query, and even ask for a direct handle if you need it for some reason, but you typically don't because the jQuery API is more predictable and safer.
That might be a fun project to tackle...
And the object id becomes the pointer then.
That would be misuse. You add the reference to the object that the id points to. 
Look guys, there is no need to reinvent the wheel.
Assuming the language chosen is C++
, then use the smart_pointers.
I wasn't disagreeing about reference-counting.
One of the reasons I didn't use any shared pointers was that they were only available in Boost and C++11. I hate boost, and I haven't had time to upgrade my compiler to a version that supports c++11 yet. Should I support MinGW 4.7 or skip directly to MinGW 4.8? It looks like MSVC 2013 still doesn't support all of c++11 (http://msdn.microsoft.com/en-us/library/hh567368.aspx), but gcc 4.8.1 is close (http://gcc.gnu.org/gcc-4.8/cxx0x_status.html). I guess I better go with mingw 4.8.1.
That would be misuse. You add the reference to the object that the id points to
So the id points to an object which contains pointers to the objects you want? I don't see how this indirection makes anything easier to use. It's just pointers again.
One of the reasons I didn't use any shared pointers was that they were only available in Boost and C++11.
You could have rolled your own. I've been using my own smart pointers for many years, but now I am gonna throw them out and use the standard ones.
I have mingw 4.8.1 and it works superbly so far.
So the id points to an object which contains pointers to the objects you want? I don't see how this indirection makes anything easier to use. It's just pointers again.
The "id" can be a "symbolic reference". Just a string that the API knows how to associate with an actual widget. If it can't find the thing then the symbolic pointer API will just throw an exception or return an error code or do nothing or whatever is appropriate when you attempt to interact. That way the underlying widget can be destroyed at any time without any segfaults. Alternatively, what usually ends up being done is something like findWidget(id), which can return nothing/null/nil if a child widget with that id doesn't exist.
I'm in favor of smart pointers, but I think that an API that doesn't rely on pointers to widgets would be ideal. Wrap the widget pointers in an abstraction layer so that the user never needs to directly interact with widget pointers.
// Completely out of context, contrived example: gui.q("#main_menu button#start_game").click([&game, &gui](E) { gui.q("#main_menu").hide(); // ... game = game.factory()->create(); game.play(); });
If it can't find the thing then the symbolic pointer API will just throw an exception or return an error code or do nothing or whatever is appropriate when you attempt to interact.
Exactly like a pointer then. For example, this:
gui.q("#main_menu button#start_game").click([&game, &gui](E)...
Is exactly the same as this:
main_menu button->start_game->click([&game, &gui](E)...
when it comes to resource management: in both cases, if the target object is not there, an exception can be thrown.
but I think that an API that doesn't rely on pointers to widgets would be ideal. Wrap the widget pointers in an abstraction layer so that the user never needs to directly interact with widget pointers.
The abstraction you describe doesn't offer anything for resource management. It offers gui scripting though.
I have mingw 4.8.1 and it works superbly so far.
Have you compiled all the dependencies for allegro though? Last time Felix The Ghost and I tried to compile allegro with all dependencies we couldn't get some of them to build with 4.8.1. I suppose it is time to try again.
Is exactly the same as this:
Sort of, at least in that particular example.
jQuery uses an expressive query language that always returns an array of matched objects. e.g., Something like the following would set the background color of every button to red.
jQuery("button").css("background-color", "red");
If there are no buttons, the code does not throw an exception because it's not an error. Nothing happens.
Have you compiled all the dependencies for allegro though?
This is OT but: I did with GCC 4.8.2 (mingw-builds project) both 64 and 32 bit flavors.
Beware of PhysFS thou, either you use the 2.0.3 or the 2.1 branch....you have to modify Cmakelists to disable -Werror (otherwise you'll be bothered by a couple "sorta innocuos" warnings 'as errors').
Is exactly the same as this:
main_menu button->start_game->click([&game, &gui](E)...
No, not quite. You can catch BAD pointers (corrupt, dangling), not just null pointers.
that's the benefit of the id. No runtime segfaults from bad pointers.
Anyhoo...
Have you compiled all the dependencies for allegro though? Last time Felix The Ghost and I tried to compile allegro with all dependencies we couldn't get some of them to build with 4.8.1. I suppose it is time to try again.
No, I am using the precompiled 4.7.0 binaries from allegro.cc. They work so far with mingw32 4.8.1. Perhaps I should not use that version and use a previous one?
Sort of, at least in that particular example. jQuery uses an expressive query language that always returns an array of matched objects
You have to go full scripting though, not just replace pointers with ids. Still, this doesn't help you in anything, you simply lose type safety without any benefits.
No, not quite. You can catch BAD pointers (corrupt, dangling), not just null pointers. that's the benefit of the id. No runtime segfaults from bad pointers.
No, you can't catch bad pointers.
Suppose you have a pointer with id 5, and the pointer is corrupt/dangling. When you call the function getPointer(5), it will return the erroneous contents of the pointer.
On the other hand, if you have an id value that is corrupted, it might return the value of another pointer.
In either case, you don't solve any problem with this approach.
On the other hand, if you have an id value that is corrupted, it might return the value of another pointer.
In either case, you don't solve any problem with this approach.
The id is not a simple index lookup.
It's encoded with other info specifically to catch bad pointers:
-active/inactive flag
-generation counter
-etc.
Of course this comes at a performance price. I was simply admiring E18.
But it's a complete development framework, so an object system is a worthwhile investment.
You could argue not, in our case.
The id is not a simple index lookup.
No matter how it is encoded, there are two cases:
1) the id itself may be corrupt.
2) the pointer that it leads to is corrupt.
In either case, a corrupted pointer will be used.
You have to go full scripting though, not just replace pointers with ids. Still, this doesn't help you in anything, you simply lose type safety without any benefits.
Scripting is a very simple concept: code as data. That is basically all that scripting is. You do not need that for this to be useful.
Imagine this:
Gui gui("gui.xml"); GuiQuery q = qui.q("<syntax to be defined>"); q.value("This was a triumph.");
q is an object of type GuiQuery (for short, but it's really a query and a result). No matter what you pass into Gui::q you will always get a GuiQuery back. The GuiQuery contains zero, one, or many widgets that match your query. The GuiQuery contains a large set of standard interface methods to interact with widgets. Event binding and triggering, styling and layout, data storage, child management, etc. Basically you can do everything you would do to a widget through the GuiQuery. When you call a method on the GuiQuery the appropriate action is taken on each widget that matched the query. If no widgets matched the query then no action is taken. No exception is thrown. Nothing happens.
This allows your code to be very safe. You can add and remove widgets on the fly. It all just works. You can even do lazy binding and apply event handlers automatically to widgets that match some query when the event actually fires. That way the widget doesn't even have to exist when you bind the event handler.
These are some of the things that jQuery accomplishes, and it works very well in practice. It allows you to very efficiently express ideas across your entire UI, and it fails gracefully. I really think it is something that should be translated back to desktop (or, as the case may be, game) GUIs.
No, you can't catch bad pointers.
Suppose you have a pointer with id 5, and the pointer is corrupt/dangling. When you call the function getPointer(5), it will return the erroneous contents of the pointer.
On the other hand, if you have an id value that is corrupted, it might return the value of another pointer.
In either case, you don't solve any problem with this approach.
You're confusing ideas. There are data variables that store virtual memory addresses. These are pointers. These are low-level and unforgiving. Do the wrong thing and your program is terminated, or corrupted, or whatever.
I believe that what Pho75_ was trying to say is that in a way a "symbolic reference" like an "id" (of whatever type) is like a pointer in that it refers to something else, but unlike a native process memory address it can be easily validated at run-time to guarantee that it is good or bad. You can verify that the "id" exists. If it doesn't exist you can choose what to do in response to using it.
Obviously if your API allows the user to manage raw memory-address pointers themselves then the API can't guarantee that those are valid. However, the API really doesn't need to let the user manage those directly. That can be abstracted away from the user. And even if you do consider it useful to expose that unsafe part of the API, you can push a safe part of the API to be used for best practices. And it becomes the user's choice to accept responsibility (just as using smart pointers would be, except with smart pointers the user can still shoot themselves in the foot). You can instead expose something high level that the API can guarantee is always safe.
Guys, snap to it. The time you've spent bickering could have been used to actually work on your GUIs. Especially axilmar's long posts.
It's pretty pointless to be involved in this thread/project if you aren't actually going to contribute to the development, especially if you already admitted that you won't.
Get to work already!
Basically you can do everything you would do to a widget through the GuiQuery. When you call a method on the GuiQuery the appropriate action is taken on each widget that matched the query. If no widgets matched the query then no action is taken. No exception is thrown. Nothing happens.
This allows your code to be very safe. You can add and remove widgets on the fly. It all just works. You can even do lazy binding and apply event handlers automatically to widgets that match some query when the event actually fires. That way the widget doesn't even have to exist when you bind the event handler.
These are some of the things that jQuery accomplishes, and it works very well in practice. It allows you to very efficiently express ideas across your entire UI, and it fails gracefully. I really think it is something that should be translated back to desktop (or, as the case may be, game) GUIs.
I simply disagree with these ideas. I want my errors to be visible as soon as I compile my application. If the widget is not there, I want the compiler to tell me that. If my widget is used erroneously, I want my compiler to tell me that.
The time and money saved by static compile time checking simply makes these kinds of ideas not worthwhile to me.
You can verify that the "id" exists.
You can verify that your id exists as long as your variable that holds the id value is not corrupted, or the hash table that holds the id information is not corrupted.
However, the API really doesn't need to let the user manage those directly.
That's not how you present it to me. You wrote the following piece of code:
gui.q("#main_menu button#start_game").click()
That's a pointer access right there: the function qui.q() accesses a pointer in order to return access to an object.
And since we are talking about untyped interfaces, the object that gui.q() returns will dispatch the click() call to an internal object via a pointer again.
You can instead expose something high level that the API can guarantee is always safe.
You can't do that in an unsafe language.
Guys, snap to it. The time you've spent bickering could have been used to actually work on your GUIs. Especially axilmar's long posts.
I DO work on my gui, as well as posting.
I simply disagree with these ideas.
We're all shocked, I'm sure. 
I want my errors to be visible as soon as I compile my application. If the widget is not there, I want the compiler to tell me that. If my widget is used erroneously, I want my compiler to tell me that.
Who's to say that it's an "error"? That is entirely up to you to define. Maybe it's an error, and maybe it isn't. In my case it wouldn't be. It isn't like saying, "do y with X." It's like saying, "if any Xs exist then do y with each." If not matching a widget is an actual programming error then you can account for that in the API so that the user can choose to make that an error. It will have to be a run-time error. A well-designed API would allow automated testing though to catch mistakes easily. No global state at all, and all external stimulus (i.e., the user) flows into the system as mockable objects.
The time and money saved by static compile time checking simply makes these kinds of ideas not worthwhile to me.
Not all errors can be checked at compile-time. That is something that you just have to accept. The computer cannot read your mind. Arguably, static typing costs more in maintenance than it makes up for in type-safety. 
You can verify that your id exists as long as your variable that holds the id value is not corrupted, or the hash table that holds the id information is not corrupted.
If you have memory corruption then your problems are bigger than GUI design semantics.
It's not even worth talking about because you should never have it.
That's not how you present it to me. You wrote the following piece of code:
gui.q("#main_menu button#start_game").click()
That's a pointer access right there: the function qui.q() accesses a pointer in order to return access to an object.
And since we are talking about untyped interfaces, the object that gui.q() returns will dispatch the click() call to an internal object via a pointer again.
A pointer that the user never has direct access to. So if at any time the API destroys that object and invalidates the pointer it will know the object no longer exists when you further attempt to access it. Or, as the case may be, it could use smart pointers to keep the object alive until the last reference goes away, while still allowing it to be removed from the GUI hierarchy, etc. The point is that the user never gets a GuiWidget * or std::shared_ptr<GuiWidget>.
You can't do that in an unsafe language.
Yes, you can. "Unsafe" just means that the language gives you low enough access to shoot yourself in the foot. Your API doesn't have to expose that. Of course, bugs are a different story altogether. You will always have those. You can't factor those into your design though because like memory corruption they are not by design.
Well I have been cleaning up WidgetHandler, allowing the user to set the root layout for the container. Now I am working on my Grid layout. It has the option to fill the cell or align to the cell only as well as to set a horizontal or vertical gap and horizontal or vertical cell padding.
How do you guys prefer drawing layout containers? If at all. But consider how they would be drawn - do you use virtual callback functions to draw them based on your preferences? So you can override the drawing in a sub class and then use that as your layout container? Or so you can draw widget backgrounds and nine patches in a derived widget? That's one way I could allow the user to customize my gui. So they can specify their own drawing routines or leave it and use the default ones or use both draw the base class first and then decorate it.
After Grid layout is Flow layout. Every layout has a halign and valign property, unlike Java cough&. You also couldn't leave empty grid markers, which sucked.
Later on I will write GridView and Table and Pin layout.
edit - I mean cmon, the JDK must have literally hundreds to thousands of contributors, surely they could have come up with some better default layouts?
A well-designed API would allow automated testing though to catch mistakes easily. No global state at all, and all external stimulus (i.e., the user) flows into the system as mockable objects.
Nobody does that tests consistently and continuously, especially for small projects.
Not all errors can be checked at compile-time. That is something that you just have to accept. The computer cannot read your mind. Arguably, static typing costs more in maintenance than it makes up for in type-safety. 
Nope. Static typing costs a lot less.
If you have memory corruption then your problems are bigger than GUI design semantics.
It's not even worth talking about because you should never have it.
We are human and we might create programs with memory corruption, at least in these unsafe languages (C and C++). So we must take that into account.
A pointer that the user never has direct access to.
It's still access via a pointer.
So if at any time the API destroys that object and invalidates the pointer it will know the object no longer exists when you further attempt to access it.
No, it's wrong. Objects should never be destroyed and pointers invalidated. In that way, the chance of creating dangling pointers is much greater than when using garbage collection (reference counting is a form of garbage collection).
The point is that the user never gets a std::shared_ptr<GuiWidget>.
Which is a stupid thing to NOT do, since it's the safest and fastest way to develop code.
Yes, you can.
No, you can't. When we say that something is safe, it must be 100% safe no matter what we do to make it unsafe. Something cannot be called unsafe when there is a ton of assumptions of things that shouldn't be done.
We're all shocked, I'm sure.
It's not my fault if you're wrong.
We are human and we might create programs with memory corruption, at least in these unsafe languages (C and C++). So we must take that into account.
You cannot account for memory corruption. Unless that memory corruption is by design. You don't seem to be capable of understanding our conversation.
I'm not at all arguing against smart pointers. They are a very good thing, and I use them myself whenever I write C++. That's entirely beside the point.
I'd prefer an API that didn't even require me to manipulate pointers directly. I want a higher-level abstraction that lets me express what I want without having to manage all of the language semantics. C++ is plenty capable of doing this, and while there needs to be ugly and unsafe code, the ugly and unsafe code can all be centralized and written once and hidden away. It's essentially the same concept as a smart pointer, but at a higher-level.
There will always be bugs, but over time those bugs can get found and fixed and it will stabilize. If you wrap all of the ugly and unsafe code up into a safe API then you can guarantee a safe library. The alternative is worse: leaving the user to manage the unsafe code themselves, in each and every program, so the number of bugs will be exponentially higher and never cease.
It's still access via a pointer.
Pointers are not the enemy. Pointers are not dangerous. Invalid pointers are dangerous. Correct code does not have invalid pointers. Pointers are an inevitability in any program, whether you know about them or not. However, pointers can be wrapped up into safe black boxes to separate your program from the error-prone work of managing pointers. That's essentially what interpreted languages do. Smart pointers are still pointers. They're only as correct as the user is setting them up.
Objects should never be destroyed and pointers invalidated.
What you describe is a memory leak. 
In that way, the chance of creating dangling pointers is much greater than when using garbage collection (reference counting is a form of garbage collection).
And now you're agreeing with me again.
It's not my fault if you're wrong.
I could say the same thing to you.
I respect your opinion, but there is no need to debate static vs dynamic typing.
There is plenty of evidence that static typing is better than dynamic typing anyway.
Although the way C/C++ are implemented, some dynamic things that could be done with static typing cannot be done in C/C++, leading you to believe that dynamic typing is better than static typing.
Therefore I am not gonna debate the need for a gui scripting language. If you want that, go ahead and implement it.
How do you guys prefer drawing layout containers? If at all. But consider how they would be drawn - do you use virtual callback functions to draw them based on your preferences? So you can override the drawing in a sub class and then use that as your layout container? Or so you can draw widget backgrounds and nine patches in a derived widget? That's one way I could allow the user to customize my gui. So they can specify their own drawing routines or leave it and use the default ones or use both draw the base class first and then decorate it.
What do you guys think? Are virtual callback functions the best way to decorate and or draw widgets through inheritance? What about function pointers? Passing functions to use? Or make widgets fully re-implement the draw function? If I use virtual call backs that is one easy way to change the way an object is drawn, by a quick subclassing of that widget.
I was thinking it would be interesting to use the Visitor Pattern for drawing:
Visitor::paintVisit(Widget* w, Graphics& g) { w->onPaint(g,this); } Widget::onPaint(Graphics& g, Visitor* v) { v->onPaint(g,this); } Visitor::onPaint(Button* b) { //paint that button! }
Or something to that extent.
This would allow the user to custom skin any widget and any subclass without needing to subclass.