Allegro.cc - Online Community

Allegro.cc Forums » Allegro Development » EGGDialog: Allegro 4-flavoured dialogs in Allegro 5

This thread is locked; no one can reply to it. rss feed Print
EGGDialog: Allegro 4-flavoured dialogs in Allegro 5
Evert
Member #794
November 2000
avatar

There are people who have a deep-rooted hatred of the Allegro 4 GUI system and feel that going anywhere near it with a 10-foot pole is a Bad Thing. There are also people who did use Allegro 4's GUI system and found it useful for what it could do.

It was felt that for Allegro 5 it would be best to leave something as divisive as a particular GUI system to third-party add-on libraries. That way, everyone can use the system they prefer and no one needs to be annoyed that what comes with Allegro doesn't satisfy their needs.

EGGDialog, then, is what grew out of my own attempts at porting an Allegro 4 game (that used the GUI for its menu system) to Allegro 5. This means that, by design, Allegro 4 dialogs can be converted to EGGDialog dialogs with minimal work. However, this doesn't mean that EGGDialog is simply an Allegro 4 dialog port. It has some additional features that I have found useful, such as:

  • Automatic placement and alignment of widgets. Simply place widgets (of a specified size) in a frame (of a specified size) and the frame will take care of placing the widgets.

  • Dialogs can be themed by specifying the colour scheme for different widgets as well as nine-patch bitmaps that should be used when drawing them.

  • Behaviour of all widgets can be modified by callback functions (in addition to or as an alternative to overloading the control function).

  • Widgets can be assigned an ID number, which means you don't have to know the order of widgets in the dialog array and you can easily change properties on the fly.

  • It's easy to add scrollbars to any custom widget because scrollbars are just standard widgets (this was not true in the original A4 GUI).

EGGDialog is something that grew out of my own needs and interest, but there seemed to be some interest in the community for an A4-style GUI library for Allegro 5, so here it is. It has a number of rough spots that I do plan to eventually improve on, but if someone else gets there first that would be great too. These include:

  • Documentation. It's pretty rudimentary and a bit of a mess. I hope the things that are different from A4/new are obvious, but they may not be. The documentation does have a list of incompatibilities/gotcha's.

  • Missing widgets. Mainly the equivalents to d_menu_proc() and d_text_list_proc(). The latter of these can be fairly easily implemented using a standard edit_proc, a listbox_proc and two callback functions.

  • Build system needs to be modified to work on Windows (no pkg-config) and could probably be more reliable.

Two examples and some screenshots to finish off:
Basic Allegro-4 style "hello world" message box:

static EGG_DIALOG hello_dlg[] = {
   /* proc                      x    y    w   h         fg         bg key  flags        d1 d2 dp1   dp2   dp3
   { egg_clear_proc,            0,   0,   0,  0, egg_black, egg_black,  0, 0,           0, 0, NULL, NULL, NULL },
   { egg_box_proc,              0,   0, 320,240, egg_black, egg_white,  0, 0,           0, 0, NULL, NULL, NULL },
   { egg_text_proc,           160,  96, 100, 32, egg_black, egg_trans,  0, 0,           ALLEGRO_ALIGN_CENTRE,0, "Hello World!", NULL, NULL },
   { egg_rounded_button_proc, 100, 160, 120, 64, egg_black, egg_white,  0, D_EXIT,      0, 0, "Goodbye!", NULL, NULL },
   { NULL }
};

Slightly more fancy "hello world" message box, using automatic placement of widgets:

static EGG_DIALOG hello_dlg[] = {
   { egg_window_frame_proc,   .fg = egg_white, .bg = egg_blue,  .d1 = ALLEGRO_ALIGN_CENTRE, .dp = "Title bar"},

   /* Vertical frame, containing a text label and a second frame */
   { egg_frame_proc,          .w = 520, .h = 240, .d1 = EGG_WALIGN_VERTICAL, .d2 = EGG_WALIGN_CENTRE, .d3 = EGG_WALIGN_CENTRE, .id = 1 },
   { egg_text_proc,           .w = 120, .h = 32, .fg = egg_black, .bg = egg_trans, .d1 = ALLEGRO_ALIGN_CENTRE, .dp = "Hello World!", .parent = 1 },

   /* Horizontal frame, containing two buttons */
   { egg_frame_proc,          .w = 520, .h = 64, .d1 = EGG_WALIGN_HORIZONTAL, .d2 = EGG_WALIGN_CENTRE, .d3 = EGG_WALIGN_CENTRE, .id = 2, .parent = 1 },
   { egg_rounded_button_proc, .w = 120, .h = 64, .fg = egg_black, .bg = egg_white, .flags = D_EXIT, .dp = "Hi!", .parent = 2  },
   { egg_rounded_button_proc, .w = 120, .h = 64, .fg = egg_black, .bg = egg_white, .flags = D_EXIT, .dp = "Goodbye!", .parent = 2  },
   { NULL }
};

And some screenshots:
{"name":"607965","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/9\/8\/983e2300a708102adf3a1857c95b3b8c.png","w":1612,"h":1252,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/9\/8\/983e2300a708102adf3a1857c95b3b8c"}607965

{"name":"607966","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/e\/6\/e651aa5b002b8571feaab553e3ac7cb9.png","w":1600,"h":1252,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/e\/6\/e651aa5b002b8571feaab553e3ac7cb9"}607966

EGGDialog is written in C99 and is available under the ZLib licence (same as Allegro 5, but see the licence file that comes with the library for additional licences that refer to specific components). Uses CMake and pkg-config in its build system (so requires some work on Windows).

Direct download link (version 0.9): http://www.eglebbk.dds.nl/program/download/EggDialog.tar.gz

Documentation page: http://www.eglebbk.dds.nl/program/eggdialog.html

I hope someone else finds this useful. All constructive feedback welcome.

Dizzy Egg
Member #10,824
March 2009
avatar

You'll be hearing from my lawyer.

----------------------------------------------------
Please check out my songs:
https://soundcloud.com/dont-rob-the-machina

kenmasters1976
Member #8,794
July 2007

Interesting. Makes my attempts at writing an Allegro GUI look lame.

Anyway, I tried building it on Windows with MinGW and I had to:

  • Hack (because I wouldn't call it fix) the CMakeLists.txt to make it work on Windows.

  • Disable the WANT_WERROR cmake option via the command line.

  • Rename the RBG macro in egg_dialog.h because it was in conflict with some definition in wingdi.h.

  • Rename the min() and max() functions in egg_dialog_proc.c because they were producing an error that I don't quite understand: egg_dialog_proc.c:5:12: error: expected identifier or '(' before 'int'.

After doing this, the library was apparently built successfully. I say apparently because the examples use the ALLEGRO_EVENT_DISPLAY_HALT_DRAWING and ALLEGRO_EVENT_DISPLAY_RESUME_DRAWING events not supported in Allegro 5.0 so I couldn't really try it. I'll try it again after I set up Allegro 5.1.

[EDIT:] After removing the ALLEGRO_EVENT_DISPLAY_HALT_DRAWING and ALLEGRO_EVENT_DISPLAY_RESUME_DRAWING event references and copying the data folder to the build folder, I was able to run the examples successfully on Windows with Allegro 5.0.10.

Trezker
Member #1,739
December 2001
avatar

I think one of the strong points of the old GUI was when you just need something quick and simple for your utilities. When you don't require beauty or complex features you could smack up some widgets and it just works.

With your improvements perhaps this new version is also well suited for a wider range of games.

Evert
Member #794
November 2000
avatar

Dizzy Egg said:

You'll be hearing from my lawyer.

Oh. Was he yours? I'm so sorry. Were you close? You will inform his family, right? You can tell them he didn't suffer. Well, I suppose you could tell them he didn't... but at least it wasn't much. It was quick. Not long anyway. Although he might have disagreed with that... I didn't ask.

Aaaanyway,

Hack (because I wouldn't call it fix) the CMakeLists.txt to make it work on Windows.

Hack is cool. Better than nothing anyway. :P
Any chance you could post your changes?

Quote:

Disable the WANT_WERROR cmake option via the command line.

Ah, yes... I should probably not have that on by default. And fix the various warnings it generates.

Quote:

Rename the RBG macro in egg_dialog.h because it was in conflict with some definition in wingdi.h.

Oh, good point. It should really be prefixed anyway.

Quote:

Rename the min() and max() functions in egg_dialog_proc.c because they were producing an error that I don't quite understand: egg_dialog_proc.c:5:12: error: expected identifier or '(' before 'int'.

Ah, I think I recognise that from somewhere: I think MinGW defines min and max in the global namespace. I don't remember what the fix/workaround was though, but I may have written that down somewhere. I'll check.

Quote:

After removing the ALLEGRO_EVENT_DISPLAY_HALT_DRAWING and ALLEGRO_EVENT_DISPLAY_RESUME_DRAWING event references

I'll put those in a version check. The only thing then is that I should probably also test whether the Allegro version you use at run time is compatible with the one you use at compile time...

Quote:

and copying the data folder to the build folder,

Ah, yes. I should automate that one too.

Quote:

I was able to run the examples successfully on Windows with Allegro 5.0.10.

Hurray!

Trezker said:

I think one of the strong points of the old GUI was when you just need something quick and simple for your utilities. When you don't require beauty or complex features you could smack up some widgets and it just works.

See, I never really understood the "beauty" argument. Sure, the default widgets and colour scheme looked a bit... retro, but it's easy to change the look by simply catching MSG_DRAW. Still, it's probably not as easy as simply applying a particular skin/theme using bitmaps.

Quote:

With your improvements perhaps this new version is also well suited for a wider range of games.

Well, I hope other people find it useful. I know I do.

One thing I haven't touched on is running multiple dialogs. Each dialog runs in its own thread and is fully self-contained, so it's not hard to have more than one of them open at the same time. You do have to do some manual window-management though in the sense that you need to make sure that the drawing order makes sense and keyboard/mouse input goes to the foreground/focus window. It shouldn't be too difficult to add some facilities to make that easier though.

Thomas Fjellstrom
Member #476
June 2000
avatar

Evert said:

The only thing then is that I should probably also test whether the Allegro version you use at run time is compatible with the one you use at compile time...

Allegro already does that. al_init / al_install_system will fail if the versions don't match.

Quote:

Each dialog runs in its own thread and is fully self-contained, so it's not hard to have more than one of them open at the same time.

Does each dialog run in a separate display (and thus context)? Or do you some how manage the rendering context (target backbuffer) to draw the separate dialogs in each thread? Maybe draw in only one thread, and events/logic only happen in the threads?

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

Evert
Member #794
November 2000
avatar

Allegro already does that. al_init / al_install_system will fail if the versions don't match.

Yes, but that doesn't help much for third-party addon libraries that can be compiled independently of both Allegro and the program that links to them.

Quote:

Does each dialog run in a separate display (and thus context)? Or do you some how manage the rendering context (target backbuffer) to draw the separate dialogs in each thread? Maybe draw in only one thread, and events/logic only happen in the threads?

EGG_DIALOG_PLAYER objects are event sources. The dialog player runs in its own thread and gets input from whatever you register it with (it has code to deal with keyboard/mouse/gamepad input as well as certain display events, and it can pass along timer events to dialog objects if you register a timer with it). If the dialog is closed or needs to be redrawn, it fires off an event of its own (EGG_EVENT_CLOSE and EGG_EVENT_REDRAW respectively).

So the normal operation is that you would start the dialog from your main thread and call the draw function when it sends you EGG_EVENT_REDRAW. This way all drawing operations are handled from the same thread.

Thomas Fjellstrom
Member #476
June 2000
avatar

Evert said:

So the normal operation is that you would start the dialog from your main thread and call the draw function when it sends you EGG_EVENT_REDRAW. This way all drawing operations are handled from the same thread.

Very cool.

I need to get around to writing some gui widgets for my Canva5 lib. 2d canvas api. its pretty neat if I do say so myself. its sorta MVC like in that you can attach multiple view ports to the same graph, each of which can be rendered anywhere including separate displays :D

So one example I had is a big graph spread across two displays, so things could move back and forth seamlessly. I was pretty happy when I got that working so smoothly.

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

kenmasters1976
Member #8,794
July 2007

Evert said:

Any chance you could post your changes?

All I did was remove every Allegro 5 find_package section from CMakeLists.txt and add the Allegro 5 libraries to the target_link_libraries of both examples. Not the most elegant solution, I know.

Dizzy Egg
Member #10,824
March 2009
avatar

Evert said:

You can tell them he didn't suffer.

now THERE'S a laugh! Poor bastard..your nasty man, nasty...took 37 hours to clean that up... :'(

----------------------------------------------------
Please check out my songs:
https://soundcloud.com/dont-rob-the-machina

Evert
Member #794
November 2000
avatar

All I did was remove every Allegro 5 find_package section from CMakeLists.txt and add the Allegro 5 libraries to the target_link_libraries of both examples. Not the most elegant solution, I know.

What are the relevant library names on Windows? Are they the same as on *nix? What other libraries need to be linked (if any)?

Elias
Member #358
May 2000

Will AGUP work with this? :)

--
"Either help out or stop whining" - Evert

kenmasters1976
Member #8,794
July 2007

Evert said:

What are the relevant library names on Windows? Are they the same as on *nix? What other libraries need to be linked (if any)?

Well, I guess the base library names are the same but right now I'm using the Allegro binaries produced by Michal Cichón which come suffixed with a number of identifiers for every possible build so I'm not sure how it can be handled.

As for linking, I just linked with all of the Allegro libraries by hardcoding them in the target_link_libraries command, like this:

target_link_libraries("hello_dialog" ${PLATFORM_LIBS} eggdialog -LC:\libs\allegro-5.0.10\lib -lallegro-5.0.10-md -lallegro_primitives-5.0.10-md ...)

As I said, not the most elegant solution but I'm just barely familiar with the cmake basics.

beoran
Member #12,636
March 2011

Great, just what I always wanted! Thanks for your hard work! :)

I'm a bit busy now with work, but I'll take a look at it whenever I can find some time, hopefully soon.

Evert
Member #794
November 2000
avatar

Elias said:

Will AGUP work with this?

I've never used it and so I don't know how it works. However, if it's just a wrapper around the default widgets that overrides MSG_DRAW, it will probably work with minor modifications (you'd still need to port the thing to A5 though).

Still, I'd use the features that are already there to customise the look (they can be expanded for sure; my focus was on getting it working first).

It also shouldn't be too hard to write a GUI for a dialog, which might be fun too. Not high on my list of things to do though.

right now I'm using the Allegro binaries produced by Michal Cichón which come suffixed with a number of identifiers for every possible build so I'm not sure how it can be handled.

As for linking, I just linked with all of the Allegro libraries by hardcoding them in the target_link_libraries command, like this:

target_link_libraries("hello_dialog" ${PLATFORM_LIBS} eggdialog -LC:\libs\allegro-5.0.10\lib -lallegro-5.0.10-md -lallegro_primitives-5.0.10-md ...)

As I said, not the most elegant solution but I'm just barely familiar with the cmake basics.

Well, it's better than no solution, so I'll probably put that in the Windows build system until someone can provide something more general. :)

I don't have Windows at all, so there's really very little I can do myself.

beoran said:

Great, just what I always wanted! Thanks for your hard work!

I'm a bit busy now with work, but I'll take a look at it whenever I can find some time, hopefully soon.

You're welcome! Hope you still think it's useful after you've had the time to look at it in more detail. ;)

kenmasters1976
Member #8,794
July 2007

I might try to find a better cmake solution for Windows but it's going to take a while.

Evert
Member #794
November 2000
avatar

I might try to find a better cmake solution for Windows but it's going to take a while.

Could you see if the following FindAllegro5.cmake works? It would only find the main Allegro 5 library, but it'd be a starting point for the other addons. You probably have to set ALLEGRO5_VERSION to "5.0.10-md" on your system; we'll handle that when we get there.

#SelectExpand
1# Find Allegro 5 2 3if(ALLEGRO5_INCLUDE_DIR) 4 # Already in cache, be silent 5 set(ALLEGRO5_FIND_QUIETLY TRUE) 6endif(ALLEGRO5_INCLUDE_DIR) 7 8if(UNIX) 9include(FindPkgConfig) 10 11pkg_search_module(ALLEGRO5 allegro-${ALLEGRO5_VERSION} allegro-debug-${ALLEGRO5_VERSION}) 12 13#message(STATUS "include: ${ALLEGRO5_INCLUDE_DIRS}") 14#message(STATUS "link flags: ${ALLEGRO5_LDFLAGS}") 15#message(STATUS "cflags: ${ALLEGRO5_CFLAGS}") 16#message(STATUS "lib dir: ${ALLEGRO5_LIBRARY_DIRS}") 17 18else(UNIX) 19 20# Win32, no pkg-config. 21# Note: CMake documentation suggests that we should treat pkg-config results as a hint only even on UNIX systems. 22find_path(ALLEGRO5_INCLUDE_DIRS allegro5/allegro.h) 23find_library(ALLEGRO5_LIBRARIES NAMES allegro-${ALLEGRO5_VERSION} allegro-debug-${ALLEGRO5_VERSION}) 24 25include(FindPackageHandleStandardArgs) 26find_package_handle_standard_args(ALLEGRO5 DEFAULT_MSG 27 ALLEGRO5_INCLUDE_DIRS ALLEGRO5_LIBRARIES) 28 29endif(UNIX) 30 31mark_as_advanced(ALLEGRO5_CFLAGS ALLEGRO5_LDFLAGS ALLEGRO5_LIBRARIES ALLEGRO5_INCLUDE_DIRS)

kenmasters1976
Member #8,794
July 2007

Yes, it worked, it detected correctly the main Allegro 5 library after setting the ALLEGRO5_VERSION. Just a small detail, while it looks for allegro-debug-${ALLEGRO5_VERSION}, the actual naming used in the Michal Cichón binaries is allegro-${ALLEGRO5_VERSION}-debug.

Edgar Reynaldo
Member #8,592
May 2007
avatar

I have my own gui, so I won't be using it, but I can appreciate the work you've put into resurrecting DIALOG's. (EGG_DIALOG's) Good for you. I did briefly use A4 dialogs but once you want to start storing information in your widget process you can have trouble.

Johan Halmén
Member #1,550
September 2001

Evert said:

There are also people who did use Allegro 4's GUI system and found it useful for what it could do.

That's me. I used A4 GUI and this a lot.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Years of thorough research have revealed that the red "x" that closes a window, really isn't red, but white on red background.

Years of thorough research have revealed that what people find beautiful about the Mandelbrot set is not the set itself, but all the rest.

Evert
Member #794
November 2000
avatar

Yes, it worked, it detected correctly the main Allegro 5 library after setting the ALLEGRO5_VERSION. Just a small detail, while it looks for allegro-debug-${ALLEGRO5_VERSION}, the actual naming used in the Michal Cichón binaries is allegro-${ALLEGRO5_VERSION}-debug.

Ok, great. That means it's just a matter of updating the other Find* packages (or actually, I should look into merging them all into one package, but that requires a little bit more research on my part). The naming scheme allegro-${ALLEGRO5_VERSION}-debug isn't a major issue, it's just a matter of looking for both permutations. Version-guessing isn't so great though, so I'll have to look for a solution to that too.

once you want to start storing information in your widget process you can have trouble.

I'm not entirely sure what you refer to, could you elaborate a bit on this? If it's something that can be avoided I'd like to do that.

One of the things I did change is that I pass around far more information to callback functions. The original Allegro 4 GUI required the use of global variables for many things, which is just evil.

I used A4 GUI and this a lot.

Interesting. It may not be too hard to update that to work with EGGDialog (maybe, although parsing C99-style struct initialisers may be more work).

Go to: