Web Analytics Made Easy - Statcounter
Skip to content

Signals and slots#

SAMSON provides a signals and slots mechanism that extensions can use to react to changes incrementally instead of recomputing everything from scratch.

This is especially useful for adaptive workflows: tools that must respond when nodes move, models change, simulations advance, or document content is added and removed.

Introduction#

Definitions#

We use the following definitions:

  • A signal is an object that emits events
  • An event is an object that is emitted by a signal
  • A slot is a function that receives an event emitted by a signal

When to use signals and slots#

Use this mechanism when your extension needs to stay synchronized with changing state over time.

Typical examples:

  • an app that monitors a selection or a set of atoms
  • an interaction model that updates incrementally
  • a visualization that reacts when an underlying model changes
  • a controller that needs to respond to other document events

Example#

Assume an app implements an adaptive algorithm that needs to be notified when some atoms changes their positions. An atom is a structural node, and the position is a property of this structural node. A position change is thus a structural event, and the app will implement a slot that receives a structural event:

void SEMyElementApp::onStructuralEvent(SBStructuralEvent* event) {

    if (event->getType() == SBStructuralEvent::ParticlePositionChanged) {

        // get the atom which sent the event

        SBAtom* atom = static_cast<SBAtom*>(event->getNode());

        // do something 

        ...

    }

}

and connect this slot to the structural signal of some atoms:

atom->connectStructuralSignalToSlot(
    this, // the pointer to the app
    SB_SLOT(&SEMyElementApp::onStructuralEvent) // the slot
    );

Whenever an atom position changes, the slot will be called immediately. When the app does not need to be notified anymore, it can disconnect atoms:

atom->disconnectStructuralSignalFromSlot(
    this, // the pointer to the app
    SB_SLOT(&SEMyElementApp::onStructuralEvent) // the slot
    );

The important pattern is:

  1. identify the object that emits the relevant event
  2. implement a slot on a receiving object
  3. connect the signal only while you need it
  4. disconnect it when the relationship is no longer needed

Types of events#

SAMSON's data graph nodes may send the following types of events:

  1. Base events: events sent by data graph nodes about their base properties (e.g. their selection flag).
  2. Document events: events sent by documents and folders.
  3. Structural events: events sent by structural models and structural nodes.
  4. Visual events: events sent by visual models.
  5. Dynamical events: events sent by dynamical models.
  6. Interaction events: events sent by interaction models.
  7. Property events: events sent by property models.
  8. Simulator events: events sent by simulators.
  9. State updater events: events sent by state updaters.
  10. Controller events: events sent by controllers.

In general, events report changes in properties of the sending object or container.

For example, when the position of an atom changes, that atom emits the corresponding structural event.

The event family is determined by the class that owns the changed property. For example:

  • an atom position change is a structural event
  • adding a structural model to a document is a document event

Important constraint#

A class must be a reference target to receive signals. As a result, slots are typically implemented on non-GUI classes such as SBDApp, which indirectly derive from SBCReferenceTarget.

This is one reason why reactive logic often belongs in data-side classes rather than directly in widget classes.

Please refer to Referencing for the lifetime and ownership model that makes this mechanism work.