r24958: This is the final text, and the final version. I'll send the release
[jelmer/samba4-debian.git] / webapps / qooxdoo-0.6.5-sdk / frontend / framework / source / class / qx / ui / tree / Tree.js
1 /* ************************************************************************
2
3    qooxdoo - the new era of web development
4
5    http://qooxdoo.org
6
7    Copyright:
8      2004-2007 1&1 Internet AG, Germany, http://www.1and1.org
9
10    License:
11      LGPL: http://www.gnu.org/licenses/lgpl.html
12      EPL: http://www.eclipse.org/org/documents/epl-v10.php
13      See the LICENSE file in the project's top-level directory for details.
14
15    Authors:
16      * Sebastian Werner (wpbasti)
17      * Andreas Ecker (ecker)
18
19 ************************************************************************ */
20
21 /* ************************************************************************
22
23 #module(ui_tree)
24
25 ************************************************************************ */
26
27 qx.OO.defineClass("qx.ui.tree.Tree", qx.ui.tree.TreeFolder,
28 function(vLabel, vIcon, vIconSelected)
29 {
30   qx.ui.tree.TreeFolder.call(this, vLabel, vIcon, vIconSelected);
31
32   // ************************************************************************
33   //   INITILISIZE MANAGER
34   // ************************************************************************
35   this._manager = new qx.manager.selection.TreeSelectionManager(this);
36
37
38   this._iconObject.setAppearance("tree-icon");
39   this._labelObject.setAppearance("tree-label");
40
41
42   // ************************************************************************
43   //   DEFAULT STATE
44   // ************************************************************************
45   // The tree should be open by default
46   this.setOpen(true);
47
48   // Fix vertical alignment of empty tree
49   this.addToFolder();
50
51
52   // ************************************************************************
53   //   KEY EVENT LISTENER
54   // ************************************************************************
55   this.addEventListener("keydown", this._onkeydown);
56   this.addEventListener("keypress", this._onkeypress);
57   this.addEventListener("keyup", this._onkeyup);
58 });
59
60
61
62
63
64 /*
65 ---------------------------------------------------------------------------
66   PROPERTIES
67 ---------------------------------------------------------------------------
68 */
69
70 qx.OO.addProperty({ name : "useDoubleClick", type : "boolean", defaultValue : false, getAlias : "useDoubleClick" });
71 qx.OO.addProperty({ name : "useTreeLines", type : "boolean", defaultValue : true, getAlias : "useTreeLines" });
72
73
74
75
76
77
78 /*
79 ---------------------------------------------------------------------------
80   MANAGER BINDING
81 ---------------------------------------------------------------------------
82 */
83
84 qx.Proto.getManager = function() {
85   return this._manager;
86 }
87
88 qx.Proto.getSelectedElement = function() {
89   return this.getManager().getSelectedItem();
90 }
91
92
93
94
95
96
97 /*
98 ---------------------------------------------------------------------------
99   QUEUE HANDLING
100 ---------------------------------------------------------------------------
101 */
102
103 qx.Proto.addChildToTreeQueue = function(vChild)
104 {
105   if (!vChild._isInTreeQueue && !vChild._isDisplayable) {
106     this.debug("Ignoring invisible child: " + vChild);
107   }
108
109   if (!vChild._isInTreeQueue && vChild._isDisplayable)
110   {
111     qx.ui.core.Widget.addToGlobalWidgetQueue(this);
112
113     if (!this._treeQueue) {
114       this._treeQueue = {};
115     }
116
117     this._treeQueue[vChild.toHashCode()] = vChild;
118
119     vChild._isInTreeQueue = true;
120   }
121 }
122
123 qx.Proto.removeChildFromTreeQueue = function(vChild)
124 {
125   if (vChild._isInTreeQueue)
126   {
127     if (this._treeQueue) {
128       delete this._treeQueue[vChild.toHashCode()];
129     }
130
131     delete vChild._isInTreeQueue;
132   }
133 }
134
135 qx.Proto.flushWidgetQueue = function() {
136   this.flushTreeQueue();
137 }
138
139 qx.Proto.flushTreeQueue = function()
140 {
141   if (!qx.lang.Object.isEmpty(this._treeQueue))
142   {
143     for (var vHashCode in this._treeQueue)
144     {
145       // this.debug("Flushing Tree Child: " + this._treeQueue[vHashCode]);
146       this._treeQueue[vHashCode].flushTree();
147       delete this._treeQueue[vHashCode]._isInTreeQueue;
148     }
149
150     delete this._treeQueue;
151   }
152 }
153
154
155
156
157
158
159
160 /*
161 ---------------------------------------------------------------------------
162   MODIFIER
163 ---------------------------------------------------------------------------
164 */
165
166 qx.Proto._modifyUseTreeLines = function(propValue, propOldValue, propData)
167 {
168   if (this._initialLayoutDone) {
169     this._updateIndent();
170   }
171
172   return true;
173 }
174
175
176
177
178
179
180
181 /*
182 ---------------------------------------------------------------------------
183   UTILITIES
184 ---------------------------------------------------------------------------
185 */
186
187 qx.Proto.getTree = function() {
188   return this;
189 }
190
191 qx.Proto.getParentFolder = function() {
192   return null;
193 }
194
195 qx.Proto.getLevel = function() {
196   return 0;
197 }
198
199
200
201
202
203
204
205
206 /*
207 ---------------------------------------------------------------------------
208   COMMON CHECKERS
209 ---------------------------------------------------------------------------
210 */
211
212 qx.ui.tree.Tree.isTreeFolder = function(vObject) {
213   return vObject && vObject instanceof qx.ui.tree.TreeFolder && !(vObject instanceof qx.ui.tree.Tree);
214 };
215
216 qx.ui.tree.Tree.isOpenTreeFolder = function(vObject) {
217   return vObject instanceof qx.ui.tree.TreeFolder && vObject.getOpen() && vObject.hasContent();
218 };
219
220
221
222
223
224
225
226 /*
227 ---------------------------------------------------------------------------
228   EVENT HANDLER
229 ---------------------------------------------------------------------------
230 */
231
232 qx.Proto._onkeydown = function(e)
233 {
234   var vSelectedItem = this.getManager().getSelectedItem();
235
236   if (e.getKeyIdentifier() == "Enter") {
237     e.preventDefault();
238
239     if (qx.ui.tree.Tree.isTreeFolder(vSelectedItem)) {
240       return vSelectedItem.toggle();
241     }
242   }
243 };
244
245
246 qx.Proto._onkeypress = function(e)
247 {
248   var vManager = this.getManager();
249   var vSelectedItem = vManager.getSelectedItem();
250
251   switch(e.getKeyIdentifier())
252   {
253     case "Left":
254       e.preventDefault();
255
256       if (qx.ui.tree.Tree.isTreeFolder(vSelectedItem))
257       {
258         if (!vSelectedItem.getOpen())
259         {
260           var vParent = vSelectedItem.getParentFolder();
261           if (vParent instanceof qx.ui.tree.TreeFolder) {
262             if (!(vParent instanceof qx.ui.tree.Tree)) {
263               vParent.close();
264             }
265
266             this.setSelectedElement(vParent);
267           }
268         }
269         else
270         {
271           return vSelectedItem.close();
272         }
273       }
274       else if (vSelectedItem instanceof qx.ui.tree.TreeFile)
275       {
276         var vParent = vSelectedItem.getParentFolder();
277         if (vParent instanceof qx.ui.tree.TreeFolder) {
278           if (!(vParent instanceof qx.ui.tree.Tree)) {
279             vParent.close();
280           }
281
282           this.setSelectedElement(vParent);
283         }
284       }
285
286       break;
287
288     case "Right":
289       e.preventDefault();
290
291       if (qx.ui.tree.Tree.isTreeFolder(vSelectedItem))
292       {
293         if (!vSelectedItem.getOpen())
294         {
295           return vSelectedItem.open();
296         }
297         else if (vSelectedItem.hasContent())
298         {
299           var vFirst = vSelectedItem.getFirstVisibleChildOfFolder();
300           this.setSelectedElement(vFirst);
301
302           if (vFirst instanceof qx.ui.tree.TreeFolder) {
303             vFirst.open();
304           }
305
306           return;
307         }
308       }
309
310       break;
311
312     default:
313       if (!this._fastUpdate)
314       {
315         this._fastUpdate = true;
316         this._oldItem = vSelectedItem;
317       }
318
319       vManager.handleKeyPress(e);
320   }
321 };
322
323
324 qx.Proto._onkeyup = function(e)
325 {
326   if (this._fastUpdate)
327   {
328     var vOldItem = this._oldItem;
329     var vNewItem = this.getManager().getSelectedItem();
330
331     vNewItem.getIconObject().addState("selected");
332
333     delete this._fastUpdate;
334     delete this._oldItem;
335   }
336 };
337
338
339 qx.Proto.getLastTreeChild = function()
340 {
341   var vLast = this;
342
343   while (vLast instanceof qx.ui.tree.AbstractTreeElement)
344   {
345     if (!(vLast instanceof qx.ui.tree.TreeFolder) || !vLast.getOpen()) {
346       return vLast;
347     }
348
349     vLast = vLast.getLastVisibleChildOfFolder();
350   }
351
352   return null;
353 };
354
355
356 qx.Proto.getFirstTreeChild = function() {
357   return this;
358 };
359
360
361 qx.Proto.setSelectedElement = function(vElement)
362 {
363   var vManager = this.getManager();
364
365   vManager.setSelectedItem(vElement);
366   vManager.setLeadItem(vElement);
367 };
368
369
370
371
372
373
374
375 /*
376 ---------------------------------------------------------------------------
377   DISPOSER
378 ---------------------------------------------------------------------------
379 */
380
381 qx.Proto.dispose = function()
382 {
383   if (this.getDisposed()) {
384     return;
385   }
386
387   this.removeEventListener("keydown", this._onkeydown);
388   this.removeEventListener("keypress", this._onkeypress);
389   this.removeEventListener("keyup", this._onkeyup);
390
391   if (this._manager)
392   {
393     this._manager.dispose();
394     this._manager = null;
395   }
396
397   delete this._oldItem;
398
399   return qx.ui.tree.TreeFolder.prototype.dispose.call(this);
400 }