0011 - Callback Chains
I mentioned in post #0008 that we’d look at callback chains and here we are. In blog entry #0010, I covered setting up an observer pattern. Today we’ll have a bit of fun combining these two. All this code should seem quite familiar, so no need to fasten your seat belt. However, there is a surprise in store, so you still might wanna hold onto your hat…
First, we’ll look at how multiple signals are chained together. It’s nothing fancy, just a few extra lines of code in the constructor of our derived button class:
No big deal. All you gotta do is tack on a bunch of signals. You can even, as done above, mix and match the callback definitions to suit your needs.
But now let’s talk about the interrupt-y bit…
Callbacks with Boolean return values allow us to hook multiple signals into a chain with the added bonus of choosing whether or not to interrupt the chain. Here are the rules again:
return(true): stop processing callbacks and return to the main loop, and
return(false): more callbacks to come, keep going.
But here’s the surprise…
Signal Handling Order
If you look at the order in which the callback signals are hooked up, you’ll see:
Further, notice that the first three are defined as being void, but the last two return Boolean values.
And when you run the example, you’ll find the signals fire, NOT in the order they’re defined in, but in this order:
And that’s because for each event, all Boolean value signals fire first and void signals fire last. Here are the events:
- a button is pressed,
- a button is released.
So only one signal is hooked up to the first event (
onPressed), three are hooked up to the second (
onRelease). But what about
onClicked? Well, the answer there is that it can’t fire until completion of the event that triggers it and that event is the
Button being pressed and released. And the
onRelease signal fires last because of all the signals with void return values, it’s hooked up last.
Now let’s move on to example #2…
Observed and Observer Buttons with Signals
This second example illustrates a signal chain.
An observer pattern lets one widget keep an eye on another and change its own behaviour based on the state of the other widget.
This time around, the
ObserverButton keeps an eye on a
WatchedButton derived from the
ToggleButton class, very much like it did in the companion code for entry #0010. But the constructor is busier:
Lots of signals being hooked up. We’re keeping the hook-ups simple so we don’t get bogged down in details unnecessary to the objective, to interrupt the signal chain.
The first two callbacks do pretty standard things. They write messages to the command shell. It’s when we get to the third callback,
takeAction(), that we see something interesting.
This is where the signal chain gets interrupted. We check the
WatchedButton (remember, it’s a
ToggleButton at heart) to see what its mode is. If the toggle is on, we change
takeAction()’s return value to false. If it’s off, we change
takeAction()’s return value to true. It almost seems backwards returning
false if we’re not done with the signal chain, but the extra little message printed out for each mode state should help you clarify this in your mind.
Now take a look at this one (it should be no trouble to work out what’s going on here):
Again, the state of the underlying
ToggleButton is checked and this time, we spit out a different message depending on what mode state we find.
WatchedButton class, derived as it is from a
ToggleButton, is almost identical to the one we used in the ToggleButton example code, so no need to go over that.
Are we done yet?
Yeah, for now, I think so. Happy D-coding and may the moon shine bright on your widgets tonight.
If you'd like to leave a comment...
Until I get time to research and install a commenting system, I ask that you try one of these options:
- come on over to the D Language Forum and look for one of the gtkDcoding announcement posts,
- drop by the gtkD Forum,
- follow the link below to email me, or
- go to the gtkDcoding Facebook page.
You can also subscribe via RSS so you won't miss anything.
© Copyright 2019 Ron Tarrant