Event propagation

What is an event?

An event is something that happens in the world. When a dog barks, for example, a sound event is generated. This sound event is represented as an object containing information about who created the sound, where, how loud, etc. As soon as the dog barks, the dog will create an instance of a sound event. Now what? Well let's say Joe is standing in the same room as the dog - unless he is deaf, he should hear the sound of the dog barking. In this particular case the dog is the event source and Joe is an event listener. There can only be one source but there can be an indefinite amount of listeners.

Of course, not all events are sound events. If Joe smiles, that's an event too. Maybe the dog will see Joe smiling and wag his tail. It's the same thing - the event travels from the source (Joe) to all potential listeners (including the dog). Note that I use the term listener even when it's not specifically a sound event, for the sake of consistency.

An event is thus something that has happened, and event propagation is about how that event travels through from the source to all potential listeners.

How does an event propagate?

The main issue here is that the event should only be propagated to those that care to listen. The issue is similar to that of GUI programming (and I got some inspiration by studying the internal design of the Java AWT classes when designing this model) - a mouse click should only be reported to those who might want to do something about a mouse click. Otherwise the windowing system would be wasting too much time sending events to components that don't care anyway.

For this reason the Physical class (see the class relations document) defines methods like wantsPropertyEvents and wantsSoundEvents. These answer true if that particular instance is interested in receiving such events.

Now there are two types of event interest: direct and indirect. If an object is directly interested in a particular type of event, for example sound events, then that means the object really wants those events and will do something about the event if it receives one. If an object is only indirectly interested in a particular type of event, then that object is only interested because one or more of it's children (or other dependents) are interested, and if it receives an event it will ignore it and propagate it along to the registered listeners.

Example - Joe & the puppy in the pub

OK let's take a concrete example. Our world consists of four objects: the pub, Joe, the puppy, and a chest. By default the sound interest of each of these objects is as follows: Let's say Joe enters the pub. As soon as he does so, he will tell the pub (in the program - not in "reality") that he is interested in sound events. This means that the pub itself is now indirectly interested in sound events. Let's say the puppy also enters the pub. The same thing will happen, although now the pub was already indirectly interested so nothing changes. The status is now: If the puppy barks now, a sound event will be produced by the puppy. The sound event will "reach" the puppy first, ie the puppy will hear his own bark (and will probably not be too surprised about that). The sound will then propagate to all listeners - in this case none, since no one has registered sound interest to the puppy. Finally, the sound will propagate "upwards" in the container hiearchy (this is the default behaviour of the Physical class from which most objects are derived - these rules are summarized later), ie the sound will be propagated to the Pub.

When the pub receives the event, it will not process it on it's own (since it couldn't care less about sound). That means the pub won't really "hear" the event, but it must still propagate it. In this case it has two listeners: Joe and the puppy. It will not propagate the event back down to the puppy, since that's the direction from which the event came, but it will propagate the event down to Joe.

Joe will receive the event and process it (which might mean that the client program that is controlling Joe will display a message such as "the puppy barks"). That's it. Joe has no listeners, and he is not allowed to send it up to his parent (the Pub) since that is where the event came from. Here's an illustration of how the event moves through the container hierarchy:

If the puppy jumps into the chest, the chest will also become an indirect listener to sound events. This means if Joe says "hi", the sound event will reach the objects in this order:

Summary of propagation rules

The basic propagation rules are defined in the Item class. These rules state that when an event is received, do the following:
  1. Process the event, if I am directly interested in it.
  2. Propagate the event to all registered listeners. Exception: never propagate the event back the same direction from which it came.
The Physical class (being a subclass if Item - see the class relations document) adds one more step to this:
  1. Process the event, if I am directly interested in it.
  2. Propagate the event to all registered listeners. Exception: never propagate the event back the same direction from which it came.
  3. Propagate the event to my parent (unless I received the event from my parent).
It is important to differ between the event sender and the event source. In the example above when Joe receives the bark event, the puppy is the definite source of the event, but the Pub is (from Joe's point of view) the sender of the event.

Current event classes

The current event hierarchy looks something like this.

To learn more details about these classes check out the Actions document.

Henrik Kniberg

Last updated: