/** * The main base class. Manages the signal system. * * @param signals Map with all connected signal handlers **/ Vn.Object = new Class ({ Tag: 'vn-object' ,Properties: {} ,signals: {} ,links: {} ,refCount: 1 ,initialize: 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) { return null; } /** * 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; } if (!this.signals[id]) this.signals[id] = []; this.signals[id].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) { var callbacks = this.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) { var callbacks = this.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) { var callbacks = this.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) { for (var signalId in this.signals) { var callbacks = this.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 () { var links = this.links; for (var key in links) links[key].disconnectByInstance (this); delete this.links; delete this.signals; } ,link: function (prop, handlers) { 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) { this.links[key] = newObject.ref (); for (var signal in handlers) newObject.on (signal, handlers[signal], this); } else if (oldObject) delete this.links[key]; } } });