Defining Signals
You can define signals on classes
using a Signal<Instance, Ret (Args...)>.
Here is a breakdown of what each template parameter means:
Instanceis the type of the object involved in the event.Ret (Args...)is the signature of any handler connected to the signal without the firstInstance *parameter.Retis the return type of a handler. Usuallyvoid.Args...are parameters passed to handlers that inform about an event.
Here are the steps to add a Signal to a class:
- Declare a
Signalas a static member of your class. - Use the
PEEL_SIGNAL_CONNECT_METHODmacro in your class to declare the.connect_signal_name ()method. - In your class initializer, initialize the
Signalstatic member with a call toSignal::create ().
GObject signal names are in kebab-case except when appearing in a function
name. Signal::create () takes in the signal name as a string in kebab-case.
The first PEEL_SIGNAL_CONNECT_METHOD argument is the signal name in
snake_case. The second argument is the Signal static member.
When an event occurs, you can call .emit () on your
Signal, and pass the Instance * and any other parameters.
Here is an example of a custom MySwitch class that emits
a signal when switched on or off.
#include <peel/GObject/Object.h>
#include <peel/GObject/ParamSpec.h>
#include <peel/class.h>
#include <peel/signal.h>
using namespace peel;
class MySwitch final : public Object
{
PEEL_SIMPLE_CLASS (MySwitch, Object)
bool state;
/* The signature of a handler is void (MySwitch *, bool) */
static Signal<MySwitch, void (bool)> sig_switched;
public:
/* Declares the connect_switched function. */
PEEL_SIGNAL_CONNECT_METHOD (switched, sig_switched)
void
set_enabled (bool new_state);
};
/* C++ requires us to explicitly define storage for a static member. */
Signal<MySwitch, void (bool)> MySwitch::sig_switched;
PEEL_CLASS_IMPL (MySwitch, "MySwitch", Object)
void
MySwitch::Class::init ()
{
sig_switched = Signal<MySwitch, void (bool)>::create ("switched");
}
void
MySwitch::set_enabled (bool new_state)
{
/* Don't emit if the state doesn't change. */
if (new_state == state)
return;
state = new_state;
sig_switched.emit (this, new_state);
}
int
main ()
{
RefPtr<MySwitch> my_switch = Object::create<MySwitch> ();
my_switch->set_enabled (false);
my_switch->connect_switched (
[] (MySwitch *, bool is_on)
{
g_print ("The switch is %s.\n", is_on ? "on" : "off");
});
my_switch->set_enabled (true);
my_switch->set_enabled (false);
}