Code::Blocks SDK events
During a Code::Blocks session, many things are happening: projects/files loading, closing, activating, saving, etc. These are interesting things that happen and various parts of Code::Blocks and its plugins are interested in them. The Code::Blocks SDK provides functions that allow a part of the code to be "subscribed" to these events (i.e. be notified when they happen). This is what we 'll look at in this article.
There are many event constants defined for the interesting events that happens inside Code::Blocks. These constants are defined in include/sdk_events.h.
Also note that there 3 different event categories:
- View layout related (CodeBlocksLayoutEvent)
- Docking system related (CodeBlocksDockEvent)
- and everything else (CodeBlocksEvent)
Subscribing to events
Up until July 6th (2007), Code::Blocks events were handled like other wxWidgets events: by declaring an event table in your class that should handle them and adding relevant event table entries.
But the event system changed radically on July 6th (2007), in order to battle some shortcomings of the wxWidgets event system (at least for our usage). While designing the new system, great attention has been paid so that plugin writers have to do minimum changes to convert their code.
The class that handles all event registrations is the central class in Code::Blocks which you use if you want to do anything with the Code::Blocks SDK: Manager. Let's see by example how would a class (e.g. SomePlugin) subscribe for the cbEVT_EDITOR_SAVE event (fired when an editor's contents are saved):
// assuming an existing member function: // void SomePlugin::OnEditorSaved(CodeBlocksEvent& event); Manager::Get()->RegisterEventSink(cbEVT_EDITOR_SAVE, new cbFunctorBase<SomePlugin, CodeBlocksEvent>(this, &SomePlugin::OnEditorSaved));
Seems difficult? It isn't, if you realize what the second argument to Manager::RegisterEventSink does.
cbEventFunctor is a class that encapsulates a this-pointer call. It is like a C function pointer except that it works with class instances (i.e. a member-function pointer). For obvious reasons it is a template class, taking two template arguments: the first is the class' name and the second is the type of the event the member function handles.
The constructor of cbEventFunctor takes two arguments: first is the class instance (we use the this pointer) and the second is the address of the member function.
And that's it. After using the above code, the defined function will be called-back on each editor saving :).
Important note: For various reasons, cbEVT_PIPEDPROCESS* and cbEVT_THREADEDTASK* events should still be bound using the old way (i.e. by adding event table entries). If this is changed in the future, this article will be updated accordingly.
Unsubscribing from events
Usually there is no need to unsubscribe from event notifications. A plugin, for example, is automatically removed from all event notifications when it is detached (deactivated, unloaded, uninstalled).
But if you really think you need to unsubscribe from events, there is a function to do that: Manager::Get()->RemoveAllEventSinksFor(void* owner). As the sole argument, pass the instance that you registered the events in the first place.
Notice that this function will remove all event notifications for the specified instance. There is no way to remove event notifications selectively. It's an all-or-nothing deal...
When to register/unregister for event notifications?
In plugins, event notifications should be registered in OnAttach(). As mentioned above, there is no need to unregister anything in OnDetach() because it is automatically done by Code::Blocks.
For code other than plugins, register whenever you think is better (depends on the actual code).
Also notice that Code::Blocks removes all registrations on shut down, so don't even think that we have memory leaks in that part ;).
If the example provided above is not enough, browse through the sources of the core/contrib Code::Blocks plugins. A few of them register for events: just search the code for Manager::Get()->RegisterEventSink. But it really is nothing difficult: just remove the event handlers from the class's event table and register with this new way.
Mandrav 13:20, 6 July 2007 (UTC)