Kigs Framework Introduction (6/8) - Signal, Slot, Notification






2.09/5 (3 votes)
A multi purpose, cross-platform, free and Open Source C++ framework. This article will focus on Signal/Slot and Notification mechanisms.
Table of Contents
Introduction
Now that we have seen how CoreModifiable
methods (Kigs Framework Introduction (4/8) - Methods) works, we are going to see in this short article how to take advantage of this mechanism to easily connect instances together.
Signals and Slots
Signals
A list of signals can be declared at compile time for a given class using helper macro SIGNALS
:
// CoreModifiable signals
SIGNALS(PreInit,
PostInit,
Uninit,
Destroy,
Update, // Called before the actual update
NotifyUpdate,
AddItem,
RemoveItem,
PrepareExport,
EndExport);
It is then possible to retrieve the list of declared signals for this class using method "GetSignalList
" :
// get the list of SimpleClass signals
std::cout << "simpleclass instance has following signals available" << std::endl;
auto signallist=simpleclass->GetSignalList();
for (const auto& s : signallist)
{
std::cout << s.toString() << std::endl;
}
Slots and Connections
A declared signal can be emitted using EmitSignal
method:
// emit signal with two parameters
EmitSignal(Signals::SendSignal1,32,64);
It's also possible with the same mechanism to send undeclared signals:
// emit a "runtime" signal (not declared with the SIGNALS macro)
EmitSignal("doSomething");
Signals can be emitted with or without parameters.
For an instance to receive a signal from another one, a connection must be setup :
// connect this "MethodWithParams" to simpleclass instance "SendSignal1" signal
KigsCore::Connect(simpleclass.get(),"SendSignal1",this, "MethodWithParams");
// connect app undeclared doSomething signal to doSomething method
KigsCore::Connect(app, "doSomething", this, "doSomething");
"MethodWithParams
" is a CoreModifiable
method declared with WRAP_METHODS
macro or with DECLARE_METHOD/COREMODIFIABLE_METHODS
. See CoreModifiable
method article in this series for details.
// Wrapped MethodWithParams
void MethodWithParams(float p1, float p2);
WRAP_METHODS(MethodWithParams);
// fixed prototype CoreModifiable method
DECLARE_METHOD(doSomething);
// list methods
COREMODIFIABLE_METHODS(doSomething);
To disconnect two instances, KigsCore::Disconnect
method is also available :
// disconnect this so SendSignal1 will not be catched anymore
CMSP simplecass=GetInstanceByPath("simpleclass");
KigsCore::Disconnect(simplecass.get(), "SendSignal1", this, "MethodWithParams");
Lambda Slots
It's also possible to connect signal to a lambda function directly:
// connect to lambda function
KigsCore::Connect(simpleclass.get(), "SendSignal2", this, "lambda", [this](int p1)
{
std::cout << "lambda received parameter " << p1 << std::endl;
});
Instance Factory Connection
It's possible to ask instance factory to create a connection for each created instance of a particular class:
// ask instance factory to add a connection on each created SimpleClass
// for the PreInit signal to call this OnSimpleClassPreInit
KigsCore::Instance()->GetInstanceFactory()->addModifiableCallback
("PreInit", this, "OnSimpleClassPreInit", "SimpleClass");
If the last parameter is not set, the connection is added for all types of created instances.
To remove the automatic connection:
// remove instance factory auto connection previously set
KigsCore::Instance()->GetInstanceFactory()->removeModifiableCallback
("PreInit", this, "OnSimpleClassPreInit");
Notifications
Another way to create connections is to use the NotificationCenter
class. NotificationCenter
can connect two instances like with signal/slot mechanism, but also notify an instance to listen for notification posted by any sender instance.
Observers
The NotificationCenter
can register observer instances:
// register this as an observer on notification "doSomethingElseNotif"
// call method CatchNotifMethod when doSomethingElseNotif is received
KigsCore::GetNotificationCenter()->addObserver(this,"CatchNotifMethod","doSomethingElseNotif");
A fourth CoreModifiable*
parameter is possible to listen to notifications only coming from the given sender instance.
To remove an observer:
// remove this as "doSomethingElseNotif" notification observer.
// a third parameter is needed if observer was set on a specific instance.
KigsCore::GetNotificationCenter()->removeObserver(this, "doSomethingElseNotif");
Post a Notification
A notification can then be sent using NotificationCenter
"postNotificationName
" method:
// post a notification "doSomethingElseNotif"
// a vector of CoreModifiable attributes can be set as second parameter :
// std::vector<CoreModifiableAttribute*>& params
// the sender can also be passed (as second or third parameter)
KigsCore::GetNotificationCenter()->postNotificationName("doSomethingElseNotif", this);
Serialization
A signal/slot connection can be set in XML adding this kind of item to an instance:
<Connect Si="SignalName" E="EmitterPath" SL="SlotName" R="ReceiverPath"/>
Emitter path and receiver path are classic CoreModifiable
search paths. "this
" or "self
" can also be used to indicate owning instance.
An observer can also be set on an instance adding this item:
<OnE N="NotificationName" A="CalledMethod"/>
Find all the sample code from this wiki section in Sample6 project (browse the code).
Already Published in this Series
- Kigs Framework Introduction (1/8) - Overview
- Kigs Framework Introduction (2/8) - CoreModifiable
- Kigs Framework Introduction (3/8) - Attributes
- Kigs Framework Introduction (4/8) - Methods
- Kigs Framework Introduction (5/8) - CoreItem
- Kigs Framework Introduction (6/8) - Signal, Slot, Notification
- Kigs Framework Introduction (7/8) - Lua Binding
- Kigs Framework Introduction (8/8) - Data Driven Application
History
- 26th February, 2020: Initial version
- 19th March, 2020: Article (7/8) added to the series and little fix in sample code
- 17th June, 2020 : Added final article of the series
- 1st March, 2023 : Article updated after framework refactory