/** * 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); } /** * Sets a group of object properties. * * @param {Object} props Properties */ ,setProperties: function (props) { for (var prop in props) this[prop] = props[prop]; } /** * Increases the object reference count. */ ,ref: function () { this._refCount++; return this; } /** * Decreases the object reference count. */ ,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; } /** * Links the object with another object. * * @param {Object} prop The linked property * @param {Object} handlers The object events to listen with */ ,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]; } } });