Updater
superclass: Object
Updater(model, updateFunction)
An Updater can be used to implement a simple Model-View-Controller architecture
in situations where a full blown controller class is not needed.
It adds itself as a dependant to the model. When the model is issued a .changed message (after its state has been changed in some way) all of its dependants, including the Updater are sent the .update message.
The Updater class then simply evalutes the updateFunction
see also: SimpleController
Examples
The most common usage is to monitor a model for changes and to update a view.
(
Sheet({ arg layout;
var bpmView, updater;
bpmView= CXLabel(layout, "tempo:_____");
updater = Updater(Tempo.default,{ // any change to Tempo
bpmView.label_("tempo:" + Tempo.bpm).refresh;
});
// fire the function manually to initially set the bpmView label
updater.update;
// tell the layout to .remove this updater when the layout and windows close
layout.removeOnClose( updater );
});
// every time you set the Tempo it will issue itself a .changed message
Tempo.tempo = 0.4
Tempo.tempo = 1.3
Tempo.tempo = 1.0
)
The updater adds itself as a dependant to the model, so its important to at some point tell the updater to remove itself (as a dependant). Otherwise it will stay in the model's dependant dictionary and will not get garbage collected. It will also continue to respond to update messages. If the window has closed this means it will try to change views that no longer exist and you will get errors.
tell the layout to .remove this updater when the layout and windows close :
layout.removeOnClose( updater );
Update the client of messages from server
The commonly used NodeWatcher class watches server notifications and issues .changed messages to the Node objects. Updater can be used to fire an updateFunction
model - the node which you want to receive server notifications for.
updateFunction -
(
// prep
s = Server.local;
n = SynthDef("Updater-help", {|out, freq|
var sin;
sin = SinOsc.ar(freq, 0.5)*EnvGen.kr(Env.triangle(4,1), doneAction:2);
Out.ar(out, sin);
}).send(s);
)
(
//create a new synth node on the server
n = Synth.new("Updater-help", [\out, 0, \freq, 220]);
//you need to register the synth with a NodeWatcher first
NodeWatcher.register(n);
//update the client of \n_end messages
Updater(n, {|node, msg|
if(msg==\n_end, {
"synth has ended".postln;
});
});
)
This could also be done using SimpleController, a related class that assumes that the second argument will be a symbol.
(
//create a new synth node on the server
n = Synth.new("Updater-help", [\out, 0, \freq, 220]);
//you need to register the synth with a NodeWatcher first
NodeWatcher.register(n);
c = SimpleController(n);
// map \n_end to an updateFunction
c.put( \n_end,{ arg node;
"synth has ended".postln;
});
)