Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Questions about GUI design

This thread is locked; no one can reply to it. rss feed Print
Questions about GUI design
DanielH
Member #934
January 2001
avatar

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"}608296

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.

axilmar said:

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 ;D 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?

axilmar said:

5) using ids. Bleh. Lessons not learned from MFC.

Confused on how would you access object without linking some sort of id to it?

l j
Member #10,584
January 2009
avatar

std::list<std::unique_ptr<widgetBaseClass>> list;? (or shared_ptr)

Edit: Update to a new version of VS?

jmasterx
Member #11,410
October 2009

The pointer version should not give an error. What is the error?

bamccaig
Member #7,536
July 2006
avatar

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.

Aikei_c
Member #14,871
January 2013
avatar

DanielH said:

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.

jmasterx
Member #11,410
October 2009

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.

DanielH
Member #934
January 2001
avatar

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.

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

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.

;)

bamccaig
Member #7,536
July 2006
avatar

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.

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

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. ???

bamccaig
Member #7,536
July 2006
avatar

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. :P

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

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

pkrcel
Member #14,001
February 2012

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:

bamccaig said:

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.

It is unlikely that Google shares your distaste for capitalism. - Derezo
If one had the eternity of time, one would do things later. - Johan Halmén

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

pkrcel said:

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.

Felix-The-Ghost
Member #9,729
April 2008
avatar

Shots fired. :-X

==========================
<--- The ghost with the most!
---------------------------
[Website] [Youtube]

axilmar
Member #1,204
April 2001

DanielH said:

Maybe you could point ;D me in the right direction. My GUI relies on inheritance of a base widget class

Use std::shared_ptr<Widget> instead of Widget*.

Quote:

and uses containers

std::shared_ptr<Widget> will work fine with containers.

Quote:

How would I be able to do this without using pointers?

You can't do it without pointers.

Quote:

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.

Quote:

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.

Quote:

I wish I could get some of you guys to join in on my EAGLE library

I am on.

Quote:

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?

Thomas Fjellstrom
Member #476
June 2000
avatar

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.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

axilmar
Member #1,204
April 2001

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.

Thomas Fjellstrom
Member #476
June 2000
avatar

axilmar said:

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.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

axilmar said:

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.

axilmar
Member #1,204
April 2001

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.

jmasterx
Member #11,410
October 2009

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.

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

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.

axilmar
Member #1,204
April 2001

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:

  1. 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.


  2. huge files with many classes in it. I am struggling to find where classes are declared.


  3. widget messages. No widget messages please, this is 2014 and c++ has virtual methods for this reason.


  4. many globals.


  5. much use of bare pointers. We shall use std::shared_ptr anywhere.


  6. no namespaces.


  7. some classes are prefixed with Eagle, some are not.


  8. instances of classes with virtual methods are passed as values to functions instead of constant references.


  9. no documentation in the headers. I am opening a file, and I see lots of declarations without comments explaining what they do.


  10. primitives like Rectangle having virtual methods. Is it necessary to have such small scale classes be virtual?


  11. 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).


  12. off-putting syntax. For example, property names with capital letters.


  13. 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.


  14. methods prefixed with Private shouldn't be protected.


  15. why is there a Camera class?


  16. widgets shouldn't have a display priority. A simple z-order suffices.


  17. class EagleColor has both integer r, g, b members and float r, g, b members.


  18. 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.


  19. 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.


  20. where are the rest of the widgets? I only found an incomplete button there. Was I looking at the wrong code?


  21. 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.

l j
Member #10,584
January 2009
avatar

Is shared_ptr really required though, wouldn't a simple unique_ptr be sufficient?



Go to: