0
1
Fork 0
hedera-web-mindshore/js/vn/object.js

203 lines
4.1 KiB
JavaScript

/**
* The main base class. Manages the signal system.
*
* @param signals Map with all connected signal handlers
*/
module.exports = new Class({
Tag: 'vn-object'
,Properties: {}
,_refCount: 1
,_signalData: null
,initialize: function(props) {
this.setProperties(props);
}
,setProperties: function(props) {
for (var prop in props)
this[prop] = props[prop];
}
,ref: function() {
this._refCount++;
return this;
}
,unref: function() {
this._refCount--;
if (this._refCount === 0)
this._destroy();
}
,loadXml: function(builder, node) {}
,appendChild: function(child) {}
,_signalInit: function() {
if (!this._signalData)
this._signalData = {
signals: {},
links: {}
};
}
/**
* Conects a signal with a function.
*
* @param {String} id The signal identifier
* @param {Function} callback The callback
* @param {Object} instance The instance
*/
,on: function(id, callback, instance) {
if (!(callback instanceof Function)) {
console.warn('Vn.Object: Invalid callback for signal \'%s\'', id);
return;
}
this._signalInit();
var callbacks = this._signalData.signals[id];
if (!callbacks)
callbacks = this._signalData.signals[id] = [];
callbacks.push({
blocked: false
,callback: callback
,instance: instance
});
}
/**
* Locks/Unlocks a signal emission to the specified object.
*
* @param {String} id The signal identifier
* @param {Function} callback The callback
* @param {Boolean} block %true for lock the signal, %false for unlock
*/
,blockSignal: function(id, callback, block, instance) {
if (!this._signalData)
return;
var callbacks = this._signalData.signals[id];
if (!callbacks)
return;
for (var i = 0; i < callbacks.length; i++)
if (callbacks[i].callback == callback
&& callbacks[i].instance == instance)
callbacks[i].blocked = block;
}
/**
* Emits a signal in the current object.
*
* @param {String} id The signal identifier
*/
,signalEmit: function(id) {
if (!this._signalData)
return;
var callbacks = this._signalData.signals[id];
if (!callbacks)
return;
var callbackArgs = [];
callbackArgs.push(this);
for (var i = 1; i < arguments.length; i++)
callbackArgs.push(arguments[i]);
for (var i = 0; i < callbacks.length; i++)
if (!callbacks[i].blocked)
callbacks[i].callback.apply(callbacks[i].instance, callbackArgs);
}
/**
* Disconnects a signal from current object.
*
* @param {String} id The signal identifier
* @param {Function} callback The connected callback
* @param {Object} instance The instance
*/
,disconnect: function(id, callback, instance) {
if (!this._signalData)
return;
var callbacks = this._signalData.signals[id];
if (!callbacks)
return;
for (var i = 0; i < callbacks.length; i++)
if (callbacks[i].callback == callback
&& callbacks[i].instance == instance)
callbacks.splice(i--, 1);
}
/**
* Disconnects all signals for the given instance.
*
* @param {Object} instance The instance
*/
,disconnectByInstance: function(instance) {
if (!this._signalData)
return;
var signals = this._signalData.signals;
for (var signalId in signals) {
var callbacks = signals[signalId];
for (var i = 0; i < callbacks.length; i++)
if (callbacks[i].instance == instance)
callbacks.splice(i--, 1);
}
}
/**
* Destroys the object, this method should only be called before losing
* the last reference to the object.
*/
,_destroy: function() {
if (!this._signalData)
return;
var links = this._signalData.links;
for (var key in links)
links[key].disconnectByInstance(this);
this._signalData = null;
}
,link: function(prop, handlers) {
this._signalInit();
var links = this._signalData.links;
for (var key in prop) {
var newObject = prop[key];
var oldObject = this[key];
if (oldObject) {
oldObject.disconnectByInstance(this);
oldObject.unref();
}
this[key] = newObject;
if (newObject) {
links[key] = newObject.ref();
for (var signal in handlers)
newObject.on(signal, handlers[signal], this);
} else if (oldObject)
delete links[key];
}
}
});