lazy-widgets
Version:
Typescript retained mode GUI for the HTML canvas API
83 lines • 2.76 kB
JavaScript
// HACK: I extends Iterable<Observable<U>> | [Observable<U>] instead of just
// extending Iterable<Observable<U>> because this forces typescript to
// prefer tuples over arrays, which is more helpful for the transformer
// user callback.
/**
* An {@link Observable} which transforms a list of input Observables into a
* single value efficiently.
*
* @category State Management
*/
export class ObservableTransformer {
/**
* The current value.
*
* Evaluated when needed. Values are cached.
*/
get value() {
if (this.dirty) {
this.cache = this.transformer(this.inputs);
this.dirty = false;
}
return this.cache;
}
/**
* @param inputs - The list of observables to use as inputs for this transformer.
* @param transformer - The actual transformer function. Takes in a list of input observables, and outputs a single value.
* @param decider - Decides whether the transformer's output value needs to be updated or not. If `undefined` (the default), then the value is always assumed to need to be updated whenever an input watcher is invoked.
*/
constructor(inputs, transformer, decider) {
this.inputs = inputs;
this.transformer = transformer;
this.decider = decider;
this.dirty = true;
/** The function callbacks called when the value is changed */
this.callbacks = new Array();
this.watcher = (_source, group) => {
if (this.decider === undefined || this.decider(this.inputs)) {
this.dirty = true;
for (const callback of this.callbacks) {
callback(this, group);
}
}
};
for (const input of this.inputs) {
input.watch(this.watcher);
}
}
destroy() {
if (this.watcher === null) {
return;
}
for (const input of this.inputs) {
input.unwatch(this.watcher);
}
this.watcher = null;
}
watch(callback, callNow = false, group) {
this.callbacks.push(callback);
if (callNow) {
this.doCallback(callback, group);
}
return this;
}
unwatch(callback) {
const i = this.callbacks.indexOf(callback);
if (i === -1) {
console.warn('unwatch called, but watcher was not registered');
}
else {
this.callbacks.splice(i, 1);
}
return this;
}
doCallback(callback, group) {
try {
callback(this, group);
}
catch (e) {
console.error('Exception in watcher:', e);
}
}
}
//# sourceMappingURL=ObservableTransformer.js.map