r20514: implement idl for DsGetNT4ChangeLog() which transferres the meta data
[ira/wip.git] / webapps / qooxdoo-0.6.3-sdk / frontend / framework / source / class / qx / core / Target.js
1 /* ************************************************************************
2
3    qooxdoo - the new era of web development
4
5    http://qooxdoo.org
6
7    Copyright:
8      2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
9
10    License:
11      LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
12
13    Authors:
14      * Sebastian Werner (wpbasti)
15      * Andreas Ecker (ecker)
16
17 ************************************************************************ */
18
19 /* ************************************************************************
20
21 #module(core)
22
23 ************************************************************************ */
24
25 /**
26  * This is the main constructor for all objects that need to be connected to qx.event.type.Event objects.
27  *
28  * In objects created with this constructor, you find functions to addEventListener or
29  * removeEventListener to or from the created object. Each event to connect to has a type in
30  * form of an identification string. This type could be the name of a regular dom event like "click" or
31  * something self-defined like "ready".
32  *
33  * @param vAutoDispose {boolean ? true} wether the object should be disposed automatically by qooxdoo
34  */
35 qx.OO.defineClass("qx.core.Target", qx.core.Object,
36 function(vAutoDispose) {
37   qx.core.Object.call(this, vAutoDispose);
38 });
39
40 /**
41  * @private
42  */
43 qx.Class.EVENTPREFIX = "evt";
44
45
46
47
48 /*
49 ---------------------------------------------------------------------------
50   EVENT CONNECTION
51 ---------------------------------------------------------------------------
52 */
53
54 /**
55  * Add event listener to an object.
56  *
57  * @param vType {string} name of the event type
58  * @param vFunction {Function} event callback function
59  * @param vObject {object ? window} reference to the 'this' variable inside the callback
60  */
61 qx.Proto.addEventListener = function(vType, vFunction, vObject)
62 {
63   if(this._disposed) {
64     return;
65   }
66
67   if(typeof vFunction !== "function") {
68     throw new Error("qx.core.Target: addEventListener(" + vType + "): '" + vFunction + "' is not a function!");
69   }
70
71   // If this is the first event of given type, we need to create a subobject
72   // that contains all the actions that will be assigned to this type
73   if (typeof this._listeners === "undefined")
74   {
75     this._listeners = {};
76     this._listeners[vType] = {};
77   }
78   else if(typeof this._listeners[vType] === "undefined")
79   {
80     this._listeners[vType] = {};
81   }
82
83   // Create a special vKey string to allow identification of each bound action
84   var vKey = qx.core.Target.EVENTPREFIX + qx.core.Object.toHashCode(vFunction) + (vObject ? "_" + qx.core.Object.toHashCode(vObject) : "");
85
86   // Finally set up the listeners object
87   this._listeners[vType][vKey] =
88   {
89     handler : vFunction,
90     object : vObject
91   }
92 }
93
94
95 /**
96  * Remove event listener from object
97  *
98  * @param vType {string} name of the event type
99  * @param vFunction {Function} event callback function
100  * @param vObject {object ? window} reference to the 'this' variable inside the callback
101  */
102 qx.Proto.removeEventListener = function(vType, vFunction, vObject)
103 {
104   if(this._disposed) {
105     return;
106   }
107
108   var vListeners = this._listeners;
109   if (!vListeners || typeof vListeners[vType] === "undefined") {
110     return;
111   }
112
113   if(typeof vFunction !== "function") {
114     throw new Error("qx.core.Target: removeEventListener(" + vType + "): '" + vFunction + "' is not a function!");
115   }
116
117   // Create a special vKey string to allow identification of each bound action
118   var vKey = qx.core.Target.EVENTPREFIX + qx.core.Object.toHashCode(vFunction) + (vObject ? "_" + qx.core.Object.toHashCode(vObject) : "");
119
120   // Delete object entry for this action
121   delete this._listeners[vType][vKey];
122 }
123
124
125
126 /*
127 ---------------------------------------------------------------------------
128   EVENT CONNECTION UTILITIES
129 ---------------------------------------------------------------------------
130 */
131
132 /**
133  * Check if there are one or more listeners for an event type.
134  *
135  * @param vType {string} name of the event type
136  */
137 qx.Proto.hasEventListeners = function(vType) {
138   return this._listeners && typeof this._listeners[vType] !== "undefined" && !qx.lang.Object.isEmpty(this._listeners[vType]);
139 }
140
141
142 /**
143  * Checks if the event is registered. If so it creates an event object and dispatches it.
144  *
145  * @param vType {string} name of the event type
146  */
147 qx.Proto.createDispatchEvent = function(vType)
148 {
149   if (this.hasEventListeners(vType)) {
150     this.dispatchEvent(new qx.event.type.Event(vType), true);
151   }
152 }
153
154
155 /**
156  * Checks if the event is registered. If so it creates an event object and dispatches it.
157  *
158  * @param vType {string} name of the event type
159  * @param vData {Object} user defined data attached to the event object
160  */
161 qx.Proto.createDispatchDataEvent = function(vType, vData)
162 {
163   if (this.hasEventListeners(vType)) {
164     this.dispatchEvent(new qx.event.type.DataEvent(vType, vData), true);
165   }
166 }
167
168
169
170 /*
171 ---------------------------------------------------------------------------
172   EVENT DISPATCH
173 ---------------------------------------------------------------------------
174 */
175
176 /**
177  * Dispatch an event
178  *
179  * @param vEvent {qx.event.type.Event} event to dispatch
180  * @param vEnableDispose {boolean} wether the event object should be disposed after all event handlers run.
181  * @return {boolean} wether the event default was prevented or not. Returns true, when the event was NOT prevented.
182  */
183 qx.Proto.dispatchEvent = function(vEvent, vEnableDispose)
184 {
185   // Ignore event if eventTarget is disposed
186   if(this.getDisposed() && this.getEnabled()) {
187     return;
188   }
189
190   if (vEvent.getTarget() == null) {
191     vEvent.setTarget(this);
192   }
193
194   if (vEvent.getCurrentTarget() == null) {
195     vEvent.setCurrentTarget(this);
196   }
197
198   // Dispatch Event
199   this._dispatchEvent(vEvent, vEnableDispose);
200
201   // Read default prevented
202   var defaultPrevented = vEvent._defaultPrevented;
203
204   // enable dispose for event?
205   vEnableDispose && vEvent.dispose();
206
207   return !defaultPrevented;
208 }
209
210
211 /**
212  * Internal event dispatch method
213  *
214  * @param vEvent {qx.event.type.Event} event to dispatch
215  */
216 qx.Proto._dispatchEvent = function(vEvent)
217 {
218   var vListeners = this._listeners;
219   if (vListeners)
220   {
221     // Setup current target
222     vEvent.setCurrentTarget(this);
223
224     // Shortcut for listener data
225     var vTypeListeners = vListeners[vEvent.getType()];
226
227     if(vTypeListeners)
228     {
229       var vFunction, vObject;
230
231       // Handle all events for the specified type
232       for (var vHashCode in vTypeListeners)
233       {
234         // Shortcuts for handler and object
235         vFunction = vTypeListeners[vHashCode].handler;
236         vObject = vTypeListeners[vHashCode].object;
237
238         // Call object function
239         try
240         {
241           if(typeof vFunction === "function") {
242             vFunction.call(qx.util.Validation.isValid(vObject) ? vObject : this, vEvent);
243           }
244         }
245         catch(ex)
246         {
247           this.error("Could not dispatch event of type \"" + vEvent.getType() + "\"", ex);
248         }
249       }
250     }
251   }
252
253   // Bubble event to parents
254   // TODO: Move this to Parent or Widget?
255   if(vEvent.getBubbles() && !vEvent.getPropagationStopped() && this.getParent)
256   {
257     var vParent = this.getParent();
258     if (vParent && !vParent.getDisposed() && vParent.getEnabled()) {
259       vParent._dispatchEvent(vEvent);
260     }
261   }
262 }
263
264
265
266
267 /*
268 ---------------------------------------------------------------------------
269   DISPOSER
270 ---------------------------------------------------------------------------
271 */
272
273 /**
274  * Destructor.
275  */
276 qx.Proto.dispose = function()
277 {
278   if(this.getDisposed()) {
279     return;
280   }
281
282   if (typeof this._listeners === "object")
283   {
284     for (var vType in this._listeners)
285     {
286       var listener = this._listeners[vType];
287       for (var vKey in listener)
288       {
289         listener[vKey] = null;
290       }
291
292       this._listeners[vType] = null;
293     }
294   }
295
296   this._listeners = null;
297
298   return qx.core.Object.prototype.dispose.call(this);
299 }