Overview
Renga API allows developers to handle various events that occur during the application's lifecycle. Plugins can respond to user actions, application state changes, selection changes, etc. Renga SDK provides event source classes for different types of events, which allow subscribing to events and providing custom handling logic.
The implementation of event handling varies between the SDK for supported languages. C++ and C# SDK provide ...EventSource helper classes, which serve as wrappers around the native COM event subscription mechanism. Since Renga API is built on COM, you can also create your own event handlers using the IConnectionPoint mechanism directly.
How to subscribe on events
To subscribe on events, first you need to create an event source and pass to its constructor the object whose events you want to subscribe on.
C++
In C++ you should call the appropriate Subscribe... method and pass any callable object, such as function, lambda expression, etc. All Subscribe... methods return unique Id of the just subscribed callback as int value.
void OnProjectClosed() { }
bool initialize(const wchar_t* pluginDir) override
{
auto pApplication = Renga::CreateApplication();
...
m_pAppEventSource = std::make_unique<Renga::ApplicationEventSource>(pApplication);
m_pAppEventSource->SubscribeProjectClosed(OnProjectClosed);
m_pAppEventSource->SubscribeProjectCreated([]()
{
});
}
C#
In C# you should call += operator on appropriate event field and pass callback function or lambda to it. Read more about C# events mechanism.
private void OnProjectClosed() { }
public bool Initialize(string pluginFolder)
{
var application = new Renga.Application();
...
m_appEventSource = new Renga.ApplicationEventSource(application);
m_appEventSource.ProjectClosed += OnProjectClosed;
m_appEventSource.ProjectCreated += () =>
{
});
}
You can subscribe multiple callbacks on a single event. Each callback will be invoked in the order they were added.
- Note
- In an event handler, you cannot modify the source object in such a way that the current event is raised again. For example, you cannot change selection in OnModelSelectionChanged event handler.
How to unsubscribe from events
To stop handling event with a specific callback, you can unsubscribe it from the event.
C++
In C++ you should call the appropriate Unsubscribe... method and pass unique callback Id to it. You can get an unique callback Id as return value of appropriate Subscribe... method.
int projectClosedCallbackId = m_pAppEventSource->SubscribeProjectClosed(OnProjectClosed);
...
m_pAppEventSource->UnsubscribeProjectClosed(projectClosedCallbackId);
C#
In C# you should call -= operator on appropriate event field and pass subscribed callback function to it. Read more about C# events mechanism.
m_appEventSource.ProjectClosed += OnProjectClosed;
...
m_appEventSource.ProjectClosed -= OnProjectClosed;
- Note
- You can also delete the event source object to unsubscribe from all its events.
How to manage event source lifetime
This section provides the basic rules for managing the lifetime of an event source:
- When you create an event source, it stores an internal reference to the source object that you pass to its constructor, so you do not need to keep the original source object alive separately. The event source will keep it alive for you.
- Event source objects must remain alive as long as your plugin needs to handle events. If an event source is destroyed, all event subscriptions are automatically unsubscribed and no further events will be delivered.
- Event subscriptions must be unsubscribed before the source object becomes invalid. If an event source continues to exist after its source object has been destroyed, Renga may attempt to deliver events to a non-existent object, leading to crashes or undefined behavior. To ensure event sources are destroyed before their source objects become invalid, use Before... events or IPlugin::Stop method.
C++
The following example shows how to properly manage an event source in C++ using std::unique_ptr. Note that the event source is stored as a class member and explicitly destroyed in stop():
#include <Renga/ApplicationEventSource.hpp>
...
{
public:
bool initialize(const wchar_t* pluginDir) override
{
auto pApplication = Renga::CreateApplication();
m_pAppEventSource = std::make_unique<Renga::ApplicationEventSource>(pApplication);
m_pAppEventSource->SubscribeProjectClosed(OnProjectClosed);
m_pAppEventSource->SubscribeProjectCreated([]()
{
});
}
void stop() override
{
m_pAppEventSource.reset();
}
private:
void OnProjectClosed() { }
std::unique_ptr<Renga::ApplicationEventSource> m_pAppEventSource;
};
The interface for plugin.
Definition IPlugin.h:40
C#
In C#, event sources implement the IDisposable interface. Note that the event source is stored as a class member and explicitly calls .Dispose() in Stop():
public class SomePlugin : public Renga.IPlugin
{
private Renga.ApplicationEventSource m_appEventSource;
public bool Initialize(string pluginFolder)
{
var application = new Renga.Application();
m_appEventSource = new Renga.ApplicationEventSource(application);
m_appEventSource.ProjectClosed += OnProjectClosed;
m_appEventSource.ProjectCreated += () =>
{
});
}
public void Stop()
{
m_appEventSource.Dispose();
}
private void OnProjectClosed()
{
}
}
See also
Related samples
- Buttons
- ModelSelection
- ModelViewEvents
- SystemEvents