GUI message handling

B5262118b588a5a420230bfbef4a2cdf
0
Stainless 151 Nov 03, 2012 at 15:35

I have to write yet another gui. Probably my 100’th or something.

Anyway, normally I use a signal class and each widget defines a signal handler per event.

So you end up something like this.

class Button : public Widget
{
private:
    signal1<Button*> OnClicked;
public:
    signal1<Button*> *get_clicked_signal();
}

The trouble with this approach is you end up creating a lot of signals on some widgets, and creating a widget is a bit messy.
By the time you have called the gets on the each event you may have a dozen lines of code.

So I’m thinking of other approaches. I don’t like the old win32 idea of having a single message pump, you end up with a huge switch statement with rubbish like this

switch (message)
{
     case BACKBUTTON_PRESSED:
       break;
     case FORWARDBUTTON_PRESSED:
       break;
      ........................................................
     case LITTLE_WIDGET_IN_THE_TOP_LEFT_CORNER_MOUSE_OVER:
      break;
     case OH_MY_GOD_IF_I_ADD_ONE_MORE_CASE_TO_THIS_SWITCH_I_WILL_KILL_MYSELF:
      break;
}

So I’m wondering if anyone has come up with a different approach.

It’s more from boredom of having to create yet another gui than anything else

12 Replies

Please log in or register to post a reply.

6837d514b487de395be51432d9cdd078
0
TheNut 179 Nov 04, 2012 at 04:37

I follow the same design as WPF, which is essentially an events and delegate approach, data binding, and behaviours. One difference from your code is that I don’t bother with a getter, I just make the events public. It keeps the code succinct and it’s handy for writing UI test stubs since I could execute the click event from an external class. Data binding and behaviours are also great to work with as they decouple business logic from my UI controls and allows me greater level of customization. There’s a lot more to it then what I can really write about here, but I loved it enough to spend the time to port it.

I’ve used a few other UI systems such as Win32, MFC, .NET forms, ClanLib’s UI, Qt, WxWidgets, and briefly took a look at CEGUI. From my experience, none come close to the design of WPF. I won’t say it will cut your coding down, it may increase it when you consider the grand design, but it most certainly keeps true to MVC design principles and really organizes your code.

A638aa42130293f319eda7fa4ba121f4
0
fireside 141 Nov 04, 2012 at 08:25

I happen to like switch/case. I like everything grouped together and call a function of like name. When using Java, I always use one listener. Seems like a waste to have more. Games are not productivity software and I think some coders get carried away with the whole thing. Scroll bars come in handy, but that’s about as far as I go, and a lot of the time, they make more work for the gamer. I’d also much rather use someone else’s because I hate doing it. I suppose that’s why there are so many around. I do like a nice background texture so at least it doesn’t look like productivity software.

B5262118b588a5a420230bfbef4a2cdf
0
Stainless 151 Nov 04, 2012 at 16:53

I love doing the pretty bits of guis, coming up with nice animation effects, etc.

The nuts and bolts of a gui are the boring bits I have done so many times before I can do it in my sleep. Literally.

For me it’s getting the balance right between versatility, and coding speed.

Say you want to add a button, you create an instance of a button, maybe set the position, set the text, maybe set the sound effect, possibly set up different graphics for each button state, etc.etc. etc.

So adding a single button to a container could quite easily require 30-40 lines of code.

So you setup default values for everything, start coding the game and find that now you want ANOTHER optional variable on the button….. :blink:

Linking a widget into the game logic is one of those points that can easily lead to huge code bloat.

In my existing GUI, you can put widgets into a container which automatically figures out the best way to display them all in the available screen space. This is fine and not that complex code, but in some circumstances one of the widgets can trigger a re-arrangement of all the widgets. Doesn’t sound complex, until you start thinking about which classes can see other classes etc.

I’m just trying to think of a new way of handling all this that can keep the code from inflating like a man stepping out of an airlock into the vacuum of space.

A638aa42130293f319eda7fa4ba121f4
0
fireside 141 Nov 04, 2012 at 17:36

So you setup default values for everything, start coding the game and find that now you want ANOTHER optional variable on the button….. :blink:

That’s why I like object oriented code. You can add a variable to the base class and it affects everything, or add a derived class if it’s only a certain button that needs different characteristics.

6837d514b487de395be51432d9cdd078
0
TheNut 179 Nov 04, 2012 at 23:46

That is one of the perks with WPF. If you want to extend logic for a control, for example adding sound playback on button clicks, you would add that as a behaviour. Behaviours themselves are classes, but designed in a way to abstract the details. When a behaviour is added to a control, its “Attached” method is called and it contains a pointer to the control. Likewise, when removed the behaviour’s “Detached” method is called. Thus, you can hook into whatever events are available in the control and act on them.

For dealing with new property types, WPF addresses this using what they call dependency objects and properties. It’s basically a dictionary object with an key and value type object. By it’s nature it is bound to the data binding engine, so any updates to a dependency object automatically notify listeners. If I wanted to render a button in a particular row and column in a grid control, I’m not going to create a new button class or extend the existing one. I’ll just define the grid row and column dependency properties for the button. If I change these values, the grid will automatically pick these up and refresh the layout.

For designing UIs, I use a similar XAML (XML) file format. The default loader handles the commonly supported controls, but it offers the ability to add extensions, so I can load any new custom control I create. By nature of dependency properties, I can define any property in XAML and have them auto loaded into my control.

[quotename=’Stainless’]from inflating like a man stepping out of an airlock into the vacuum of space.[/quote]
Or like in Total Recall where the eyes bulge out and the body explodes violently. Alas, reality is not that exciting :)

B20d81438814b6ba7da7ff8eb502d039
0
Vilem_Otte 117 Nov 05, 2012 at 01:21

Am I really the only guy here (don’t call me masochist again, please :D ), who uses GUI system created in native C with function pointers (e.g. no derived classes (actually no classes at all), etc.)?

Basically this GUI originated a long time ago (and it was used in quite a lot of applications), the thing is that I’ve never used it actually in game, only inside database apps. :)
On my defence, the code isn’t a unusable and unmaintable bloat (which OOP codes often becomes), and imo it’s even a bit easier to use than to work with OOP model - you got just structures containing other structures (like every structure in GUI contains widget_t structure) and function pointers (standard onMouseOver, onClick, etc. etc. - you know it), invoked when needed. I think OOP here would bring (and brings) some complications that would made it harder to use.

B5262118b588a5a420230bfbef4a2cdf
0
Stainless 151 Nov 05, 2012 at 09:51

ermmmmmm YES! :D

I really do think you are the only one. :P

I had to port a browser a year or so ago that used a similar system. The structures used unions to emulate a class like structure. Porting it was an absolute nightmare. Alignment issues caused crashes and subtle bugs all over the place. In the end I had to go to Germany (in November…. COLD…) and explain the problem then parse the entire source code tree adding macros to the end of every structure.

I like the idea of behaviours being attached… hmmm got me thinking at last.

8676d29610e6c98d6dd2d9c38528cd9c
0
alphadog 101 Nov 07, 2012 at 16:25

What you are looking for is an event bus which decouples all your widgets. Widgets publish (events (basically a pile of data) into the bus. Other code blocks subscribe to some or all events. Nice thing is, done right, this can be altered dynamically at run-time if needed.

There are tons out there of various levels of complexity, but basically it boils down to two classes/interfaces/thingee, depending on language used:

  • Some thingee to abstractly represent the event/data. It is a wrapper for arbitrary data related to the event.
  • A thingee to represent the bus. Usually a singleton. It manages the pub-sub linkages.

Google is your friend at this point. If you need any keyword help, just holla…

B5262118b588a5a420230bfbef4a2cdf
0
Stainless 151 Nov 07, 2012 at 19:09

Yes, you really have me thinking now. Thanks.

What I want to be able to do is global animation effects. So you have a display with a bunch of widgets all in view and live, you do something to one of them and all the widgets animate. Some kill themselves, some move….. whatever I can think of.

So attaching a behavior to a widget and link the behavior to an event …….. yes starting to look cool.

B20d81438814b6ba7da7ff8eb502d039
0
Vilem_Otte 117 Nov 07, 2012 at 19:31

Basically this gets me to something maybe not directly related, but interesting. I’ve not tried it (yet), but it might worth try:

You have a widget object/struct that has function pointers (virtual methods, etc.) for events (like onClick, onMouseOver, etc. - like i described), and it points to some renderable (even 3D) object - basically this object will inform widget object about events (e.g. whether it has to call some function/method, along with arguments for these functions).

The renderable object can then be any 2D/3D object in the scene, that can be F.e. animated (it will have controller attached - so you can define it’s behaviour in a script) - that way you could achieve a lot of very fancy stuff with gui - from basic moving of buttons, to even some hardcore effects (defragmenting buttons to parts and let them burn, on closing the window containing them - for example - hope you get what i mean), etc.

B5262118b588a5a420230bfbef4a2cdf
0
Stainless 151 Nov 07, 2012 at 19:47

Villem, your now seeing what I want to be able to do ;) , I’m just thinking about the best way to do it.

I personally don’t like having named event handlers, you would need an OnEvent handler for every event you want to react to, and the code will bloat.

Having behaviors that can be attached to any widget means that in each widget you just need a vector containing all the handlers. No code bloat as you just need a single class for each behavior and a singleton to invoke them.

Still thinking about the design…

8676d29610e6c98d6dd2d9c38528cd9c
0
alphadog 101 Nov 07, 2012 at 22:06

It’s just some sort of pub-sub/observer pattern. In Qt it’s signals and slots. You can have a more coupled pub-sub, or use a bus to decouple it.

http://www.cs.ru.nl/\~pieter/oss/manyfaces.pdf
http://www.comicfanboy.net/node/90
etc…