My OnEvent() function has too many levels of nested switch-case statements. Currently, I have factored case bodies into helper functions. What alternatives/strategies should I explore to reduce the complexity of nested switch-case statements?
/// Does stuff when a Menu Bar item is selected.
bool EditorGui::onMenuItemSelected( irr::gui::IGUIContextMenu* pMenuItem )
{
irr::s32 menuItemId = pMenuItem->getItemCommandId( pMenuItem->getSelectedItem() ); // Get id of calling menu item
switch( menuItemId )
{
case GUID_FILE_NEWPROJECT :
{
return onFileNewProject();
}
case GUID_FILE_OPENPROJECT :
{
return onFileOpenProject();
}
case GUID_FILE_SAVEPROJECT :
{
return onFileSaveProject();
}
case GUID_FILE_EXIT :
{
onFileExit();
}
default :
return false;
}
}
First - as long as the project is small it's not even so bad having a long case/switch as you know at least exactly where to look for events :-)
But when it gets larger I also use other strategies. Simplest one is - use several event-receivers which you call from your main event-receiver. I generally have one such eventhandler per ui-dialog. Where by dialog I mean - a group of active ui-elements (which usually have a common background). You can then decide to always call all of them - or only for your active dialog (which can be one or several - in my case it's usually one). Example here: http://irrlicht.sourceforge.net/forum// ... hp?t=26176
I kinda use those in my racer game. Check https://bitbucket.org/mzeilfelder/trunk_hc1/src the src/gui_dialog.cpp/.h for my main dialog class and you might also take a look at my main event receiver which is in src/event_receiver_base.cpp/.h
Examples with code for my dialogs themself are in src/gui_dialogs sub-folder.
And the most comfortable (but also slowest) solution would be writing a signal/slot system on top of events like Qt has. But I have no example for that yet.
I have a dynamic event receiver, it can grow and shrink as i see fit. It is very simple, and maybe not very efficient, but does the job. I suggest you to use the least receivers possible, but don't underestimate it either. 20-30 shouldn't be a problem even for real time
#ifndef _DYNAMICEVENTRECEIVER_H_
#define _DYNAMICEVENTRECEIVER_H_
#include <irrlicht.h>
//This is a dynamic event receiver. The idea behind is to have an extensible receiver which can be enlarged or reduced at will, and which can vary its behavior in run time.
//The usage is as follows: you set this as the main receiver of the irrlicht device, and then, you can register and/or remove event receivers from it. The receivers just have to follow
//the same rules as Irrlicht receivers, if a receiver wants to end the processing of an event, it must return true, otherwise, it must return false. If an event returns true, the
//dynamic receiver returns immediately.
//Serves for instance, to remove certain routines from memory when certain parts of the program are reached and change them for others, simplifying its design, or to build
//complex behaviors through the usage of simpler event receivers which otherwise, could create an event receiver very complex to maintain, or even, to write.
class dynamicEventReceiver : public irr::IEventReceiver
{
irr::core::list<IEventReceiver*> receivers;
public:
//DTOR
~dynamicEventReceiver();
//EVENT manager
virtual bool OnEvent(const irr::SEvent& event);
//Registers a new event receiver, returns the index of the newly inserted receiver, useful for instance if we want to delete it
irr::s32 registerEventReceiver(IEventReceiver* rec);
//Unregisters an event receiver by receiver pointer value
void unregisterEventReceiver(IEventReceiver* rec);
//Unregisters an event receiver by its index
void unregisterEventReceiver(irr::u32);
};
#endif
Depending on the complexity of the GUI system in my program, I usually create wrapper GUI elements that do all of the event handling for their children. This is faster than the event dispatch but it may require more work.