SwingGUI – Java-based GUI classes

last mod: 13-jan-08 sciss

 

UpdateListener

This class is somewhat similar to Updater from the Crucial-library, but with a few extras. It implements the update method needed to register dependants with objects, so it acts as an observer in the observer software-design pattern, and can also be used in model-view-controller (mvc) design.

When the observed object is issued a changed message (after its state has been changed in some way) all of its dependants – including the UpdateListener – are sent the update message. The UpdateListener forwards this call to the Function that was passed in its constructor:

    UpdateListener.new( <(Function) update>, [ <(Symbol) what> ])
	

where update is a Function that will get invoked with the first argument being the UpdateListener itself, followed by all arguments of the update call. The optional what argument is a filter to limit update forwarding to a specific type of update-message (see below).

When you use this plain constructor, the listener needs to be added as dependant to some object / model, using the addTo( <(Object) object> ) method. As a shorthand, the contructor method

    UpdateListener.newFor( <(Object) object>, <(Function) update>, [ <(Symbol) what> ])

can be used. Examples:

s.boot;

x = Synth( \default, [ \amp, 0.2 ]);
x.register;     // now a NodeWatcher will call 'changed' on x
// create and add a new UpdateListener that tracks changes of x by printing them
// to the post-window:
u = UpdateListener.newFor( x, { arg upd, obj ... info; ([ obj ] ++ info).postln });
// isListening reports whether the UpdateListener is still a dependant
u.isListening;  // --> true
x.run( false ); // --> [ Synth("default" : 1000), n_off ]
x.run( true );  // --> [ Synth("default" : 1000), n_on ]
x.release;      // --> [ Synth("default" : 1000), n_end ]
u.remove;       // removes the dependant from all observed objects
u.isListening;  // --> false

x = Synth( \default, [ \freq, 441, \pan, -1, \amp, 0.2 ]).register;
y = Synth( \default, [ \freq, 662, \pan,  1, \amp, 0.2 ]).register;
z = Synth( \default, [ \freq, 332, \pan,  0, \amp, 0.2 ]).register;
u = UpdateListener({ "update!".postln });
// it is allowed to add the listener to several objects
u.addTo( x );
u.addTo( y );
u.addTo( z );
x.free;
u.removeFrom( y );      // remove dependant only from y
u.isListeningTo( y );   // --> false
u.isListeningTo( z );   // --> true
y.free;                 // ... so this will not notify u anymore
u.verbose = true;       // prints out invocations the post-window (independent of the update function)
z.free;
u.removeFromAll;        // synonym with 'remove'

 

Using the 'what' filter-argument

x = Synth.basicNew( \default ).register;
// now a listener that only registers changes of type \n_go:
u = UpdateListener.newFor( x, { arg ... args; args.postln }, \n_go );
x.server.listSendMsg( x.newMsg( args: [ \amp, 0.2 ]));
x.run( false );
x.run( true );
x.free;
u.remove;