The short: How to make sure that "statically" declared IDs for events and/or widgets don't clash across a medium to larger size project ?
...and the long:
One way of dealing with IDs in WxWidgets is to declare them by means of enumerations per compilation-unit, i.e. in the widget's source-file. However, when the IDs are used in WxWidgets' event-handling, they should or must be globally unique. Some don't need to be globally unique, but I think it's safer, if they all are, otherwise there's potential for runtime-"clashes", that don't trigger any warning - the event is simply handled by another widget. Unfortunately, I came across this issue a couple of times (inherited code-base) - they are hard to track down and rather annoying, unless I'm missing something. Anyway, I want to sort this out, once and for all :-)
I know, that WxWidgets also supports dynamic binding, and we/I use it in some places. However, changing the code for all the "statically" declared IDs would be way too much effort. So essentially what I have are many separate source-files (>60) where there are enumerations starting at wxID_HIGHEST with some (seemingly) arbitrary offset. I do think that the offset is arbitrary, likely to have been added to fix single cases of the above ID-clash problem. Anyway, putting all enumerations into a single file/enumeration seems a bit ugly, because it would be an incredibly long list.
So here is what I've been thinking: I maintain MIN/MAX-IDs for the different widgets in a single header-file using a single enumeration, and provide two macros that BEGIN and END a given ID-enumeration. The END-macro should also check that the declared MAX-ID is not exceeded. Does that sound sensible ? What are common ways of addressing the ID-clash issue ?
My intended solution looks something like the following. I plan to add a function that deals with IDs for dynamic binding. I know that WxWidgets provides related functionality with ID-reference-counting, however, I thought just while I'm at it... It is intended to be as platform-independent as possible.
#include <wx/defs.h>
#define NUM_OF_DYNAMIC_AUTO_IDS 500
namespace WxWidgetIdHelper {
enum WxWidgetIDsEnum {
MIN_DYNAMIC_AUTO_ID = wxID_HIGHEST + 1,
MAX_DYNAMIC_AUTO_ID = MIN_DYNAMIC_AUTO_ID + NUM_OF_DYNAMIC_AUTO_IDS,
STATIC_ID_OFFSET = MAX_DYNAMIC_AUTO_ID + 1,
Widget1_MIN_ID = STATIC_ID_OFFSET + 1,
Widget1_MAX_ID = Widget1_MIN_ID + 20,
Widget2_MIN_ID = Widget1_MAX_ID + 1,
Widget2_MAX_ID = Widget2_MIN_ID + 20,
...
};
template<bool> struct MaxIdCheck;
template<> struct MaxIdCheck<false> {};
}
#define BEGIN_WXWIDGET_ID_ENUM(CLASSNAME) \
enum CLASSNAME##_##WXWIDGET_IDs { \
CLASSNAME##_##MIN_ID = WxWidgetIdHelper##::##CLASSNAME##_##MIN_ID,
#define END_WXWIDGET_ID_ENUM(CLASSNAME) CLASSNAME##_##MAX_ID }; \
WxWidgetIdHelper::MaxIdCheck< \
( CLASSNAME##_##MAX_ID>WxWidgetIdHelper::CLASSNAME##_##MAX_ID ) > \
INCREASE##_##CLASSNAME##_##MAX_ID_in_WxWidgetIdHelper_h;