1 /**
  2  * Copyright (C) 2009-2011 Klaus Reimer <k@ailis.de>
  3  * See LICENSE.txt for licensing information.
  4  * 
  5  * @require twodee.js
  6  */
  7 
  8 /**
  9  * Constructs a new twodee object.
 10  * 
 11  * @constructor
 12  * @class 
 13  * The base class for other twodee objects.
 14  */
 15 twodee.Object = function()
 16 {
 17     this.slots = [];
 18 };
 19 
 20 /**
 21  * The connected slots.
 22  * 
 23  * @private
 24  * @type {Object.<string, Array.<{func:function(...),context:Object}>>}
 25  */
 26 twodee.Object.prototype.slots = null;
 27 
 28 /**
 29  * Returns the array with slots connected to the specified signal. If it
 30  * does not exist then a new empty array is created for this signal.
 31  * 
 32  * @param {string} signal
 33  *            The signal
 34  * @return {Array.<{func:function(...),context:Object}>} The array with connected slots.
 35  * @private
 36  */
 37 twodee.Object.prototype.getSlots = function(signal)
 38 {	
 39     var slots; 
 40     
 41     slots = this.slots[signal];
 42     if (!slots) slots = this.slots[signal] = [];
 43     return slots;
 44 };
 45 
 46 /**
 47  * Connects a slot to a signal.
 48  * 
 49  * @param {string} signal
 50  *            The signal
 51  * @param {function(...)} func
 52  *            The slot function
 53  * @param {Object} context
 54  *            The function context (Optional, defaults to "window")
 55  */
 56 twodee.Object.prototype.connect = function(signal, func, context)
 57 {
 58     this.getSlots(signal).push({ func: func, context: context ? context : window});
 59 };
 60 
 61 /**
 62  * Disconnects a slot from a signal.
 63  * 
 64  * @param {string} signal
 65  *            The signal. If not specified then everything is disconnected
 66  * @param {function(...)} func
 67  *            The slot function. If not specified then all handlers for 
 68  *            specified signal are disconnected
 69  * @param {Object} context
 70  *            The function context (Optional, defaults to "window")
 71  */
 72 twodee.Object.prototype.disconnect = function(signal, func, context)
 73 {
 74     var slots, i, slot;
 75     
 76     // If no signal was specified then all signal handlers are disconnected
 77     if (!signal)
 78     {
 79         this.slots = null;
 80         return;
 81     }
 82     if (!context) context = window;
 83     slots = this.getSlots(signal);
 84     for (i = slots.length - 1; i >= 0; i--)
 85     {
 86     	slot = slots[i];
 87         if (!func || (slot.func == func && slot.context == context))
 88         {
 89             slots.splice(i, 1);
 90         }
 91     }
 92 };
 93 
 94 /**
 95  * Sends a signal.
 96  * 
 97  * @param {string} signal
 98  *            The signal to send
 99  * @param {...} varargs
100  *            Variable number of optional arguments passed to the slots
101  */
102 twodee.Object.prototype.sendSignal = function(signal, varargs)
103 {
104     var slots, i, args, slot;
105     
106     // Build arguments array 
107     args = [];
108     for (i = 1; i < arguments.length; i++) args.push(arguments[i]);
109     
110     // Call all connected slots
111     slots = this.getSlots(signal);
112     for (i = slots.length - 1; i >= 0; i--)
113     {
114     	slot = slots[i];
115         slot.func.apply(slot.context, args);
116     }
117 };
118