1 /* ************************************************************************
3 qooxdoo - the new era of web development
8 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
12 LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
15 * Sebastian Werner (wpbasti)
16 * Andreas Ecker (ecker)
17 * Derrell Lipman (derrell)
19 ************************************************************************ */
21 /* ************************************************************************
23 #module(ui_treefullcontrol)
25 ************************************************************************ */
27 qx.OO.defineClass("qx.ui.treefullcontrol.AbstractTreeElement", qx.ui.layout.BoxLayout,
28 function(treeRowStructure)
30 if (this.classname == qx.ui.treefullcontrol.AbstractTreeElement.ABSTRACT_CLASS) {
31 throw new Error("Please omit the usage of qx.ui.treefullcontrol.AbstractTreeElement directly. Choose between qx.ui.treefullcontrol.TreeFolder, qx.ui.treefullcontrol.TreeFolderSimple, qx.ui.treefullcontrol.TreeFile and qx.ui.treefullcontrol.TreeFileSimple instead!");
34 if (treeRowStructure !== qx.ui.treefullcontrol.TreeRowStructure.getInstance())
36 throw new Error("A qx.ui.treefullcontrol.TreeRowStructure parameter is required.");
39 // Precreate subwidgets
40 this._indentObject = treeRowStructure._indentObject;
41 this._iconObject = treeRowStructure._iconObject;
42 this._labelObject = treeRowStructure._labelObject;
45 this._indentObject.setAnonymous(true);
46 this._iconObject.setAnonymous(true);
47 this._labelObject.setAnonymous(true);
49 // Behaviour and Hard Styling
50 this._labelObject.setSelectable(false);
51 this._labelObject.setStyleProperty("lineHeight",
54 qx.ui.layout.BoxLayout.call(this, "horizontal");
56 if (qx.util.Validation.isValid(treeRowStructure._label)) {
57 this.setLabel(treeRowStructure._label);
61 this.setSelectable(false);
63 // Base URL used for indent images
64 this.BASE_URI = qx.manager.object.AliasManager.getInstance().resolvePath("widget/tree/");
67 * Add all of the objects which are to be in the horizontal layout.
69 for (var i = 0; i < treeRowStructure._fields.length; i++)
71 this.add(treeRowStructure._fields[i]);
75 if ((treeRowStructure._icons.unselected != null) &&
76 (qx.util.Validation.isValidString(treeRowStructure._icons.unselected))) {
77 this.setIcon(treeRowStructure._icons.unselected);
78 this.setIconSelected(treeRowStructure._icons.unselected);
80 if ((treeRowStructure._icons.selected != null) &&
81 (qx.util.Validation.isValidString(treeRowStructure._icons.selected))) {
82 this.setIconSelected(treeRowStructure._icons.selected);
86 this._iconObject.setSource(this._evalCurrentIcon());
89 this._iconObject.setAppearance("tree-element-icon");
90 this._labelObject.setAppearance("tree-element-label");
92 // Register event listeners
93 this.addEventListener("mousedown", this._onmousedown);
94 this.addEventListener("mouseup", this._onmouseup);
97 qx.ui.treefullcontrol.AbstractTreeElement.ABSTRACT_CLASS = "qx.ui.treefullcontrol.AbstractTreeElement";
103 ---------------------------------------------------------------------------
105 ---------------------------------------------------------------------------
108 qx.OO.changeProperty({ name : "appearance",
110 defaultValue : "tree-element"
116 qx.OO.addProperty({ name : "icon",
120 qx.OO.addProperty({ name : "iconSelected",
125 The label/caption/text of the qx.ui.basic.Atom instance
127 qx.OO.addProperty({ name : "label",
134 qx.OO.addProperty({ name : "selected",
145 ---------------------------------------------------------------------------
147 ---------------------------------------------------------------------------
150 qx.Proto._modifyLabel = function(propValue, propOldValue, propData)
152 if (this._labelObject) {
153 this._labelObject.setHtml(propValue);
159 qx.Proto._modifySelected = function(propValue, propOldValue, propData)
162 this.addState("selected");
163 this._labelObject.addState("selected");
165 this.removeState("selected");
166 this._labelObject.removeState("selected");
169 var vTree = this.getTree();
170 if (!vTree._fastUpdate ||
171 (propOldValue && vTree._oldItem == this)) {
172 this._iconObject.setSource(this._evalCurrentIcon());
175 this._iconObject.addState("selected");
177 this._iconObject.removeState("selected");
181 var vManager = this.getTree().getManager();
183 if (propOldValue && vManager.getSelectedItem() == this)
185 vManager.deselectAll();
187 else if (propValue && vManager.getSelectedItem() != this)
189 vManager.setSelectedItem(this);
195 qx.Proto._evalCurrentIcon = function()
197 if (this.getSelected() && this.getIconSelected()) {
198 return this.getIconSelected();
200 return this.getIcon() || "icon/16/file-new.png";
209 ---------------------------------------------------------------------------
211 ---------------------------------------------------------------------------
214 qx.Proto.getParentFolder = function()
217 return this.getParent().getParent();
223 qx.Proto.getLevel = function()
225 var vParentFolder = this.getParentFolder();
226 return vParentFolder ? vParentFolder.getLevel() + 1 : null;
229 qx.Proto.getTree = function()
231 var vParentFolder = this.getParentFolder();
232 return vParentFolder ? vParentFolder.getTree() : null;
235 qx.Proto.getIndentObject = function() {
236 return this._indentObject;
239 qx.Proto.getIconObject = function() {
240 return this._iconObject;
243 qx.Proto.getLabelObject = function() {
244 return this._labelObject;
248 * Obtain the entire hierarchy of labels from the root down to the current
253 * When called by the user, arr should typically be an empty array. Each
254 * level from the current node upwards will push its label onto the array.
256 qx.Proto.getHierarchy = function(vArr) {
257 // Add our label to the array
258 if (this._labelObject) {
259 vArr.unshift(this._labelObject.getHtml());
262 // Get the parent folder
263 var parent = this.getParentFolder();
267 // ... then add it and its ancestors' labels to the array.
268 parent.getHierarchy(vArr);
271 // Give 'em what they came for
279 ---------------------------------------------------------------------------
281 ---------------------------------------------------------------------------
284 qx.Proto.addToTreeQueue = function()
286 var vTree = this.getTree();
288 vTree.addChildToTreeQueue(this);
292 qx.Proto.removeFromTreeQueue = function()
294 var vTree = this.getTree();
296 vTree.removeChildFromTreeQueue(this);
300 qx.Proto.addToCustomQueues = function(vHint)
302 this.addToTreeQueue();
304 qx.ui.layout.BoxLayout.prototype.addToCustomQueues.call(this, vHint);
307 qx.Proto.removeFromCustomQueues = function(vHint)
309 this.removeFromTreeQueue();
311 qx.ui.layout.BoxLayout.prototype.removeFromCustomQueues.call(this, vHint);
322 ---------------------------------------------------------------------------
324 ---------------------------------------------------------------------------
327 qx.Proto._modifyParent = function(propValue, propOldValue, propData)
329 qx.ui.layout.BoxLayout.prototype._modifyParent.call(this, propValue, propOldValue, propData);
331 // Be sure to update previous folder also if it is closed currently
332 // (plus/minus symbol)
334 !propOldValue.isDisplayable() &&
335 propOldValue.getParent() &&
336 propOldValue.getParent().isDisplayable()) {
337 propOldValue.getParent().addToTreeQueue();
340 // Be sure to update new folder also if it is closed currently
341 // (plus/minus symbol)
343 !propValue.isDisplayable() &&
344 propValue.getParent() &&
345 propValue.getParent().isDisplayable()) {
346 propValue.getParent().addToTreeQueue();
352 qx.Proto._handleDisplayableCustom = function(vDisplayable, vParent, vHint)
354 qx.ui.layout.BoxLayout.prototype._handleDisplayableCustom.call(this,
361 var vParentFolder = this.getParentFolder();
362 var vPreviousParentFolder = this._previousParentFolder;
364 if (vPreviousParentFolder)
366 if (this._wasLastVisibleChild)
368 vPreviousParentFolder._updateIndent();
370 else if (!vPreviousParentFolder.hasContent())
372 vPreviousParentFolder.addToTreeQueue();
377 vParentFolder.isDisplayable() &&
378 vParentFolder._initialLayoutDone) {
379 vParentFolder.addToTreeQueue();
382 if (this.isLastVisibleChild())
384 var vPrev = this.getPreviousVisibleSibling();
387 vPrev instanceof qx.ui.treefullcontrol.AbstractTreeElement) {
388 vPrev._updateIndent();
393 this._updateIndent();
405 ---------------------------------------------------------------------------
407 ---------------------------------------------------------------------------
410 qx.Proto._onmousedown = function(e)
412 this.getTree().getManager().handleMouseDown(this, e);
416 qx.Proto._onmouseup = qx.util.Return.returnTrue;
423 ---------------------------------------------------------------------------
425 ---------------------------------------------------------------------------
428 qx.Proto.flushTree = function()
430 // store information for update process
431 this._previousParentFolder = this.getParentFolder();
432 this._wasLastVisibleChild = this.isLastVisibleChild();
434 // generate html for indent area
435 var vLevel = this.getLevel();
436 var vTree = this.getTree();
439 var vCurrentObject = this;
441 var vMaxLevel = vLevel;
443 // If we're displaying the open/close button for the root node (normal)...
444 if (vTree.getRootOpenClose()) {
445 // ... then we need one more level
446 vMaxLevel = vLevel + 1;
449 // If we're not displaying the root node (creating virtual roots)...
450 if (vTree.hideNode()) {
451 // ... then start one level higher
455 for (var i=vMinLevel; i<vMaxLevel; i++)
457 vImage = vCurrentObject.getIndentSymbol(vTree.getUseTreeLines(),
464 vHtml.push("<img style=\"position:absolute;top:0px;left:");
466 // location of image; Root's image could be left of margin (invisible)
467 vHtml.push((vMaxLevel-i-1) * 19);
469 vHtml.push("px\" src=\"");
470 vHtml.push(this.BASE_URI);
477 vCurrentObject = vCurrentObject.getParentFolder();
480 this._indentObject.setHtml(vHtml.join(""));
481 this._indentObject.setWidth((vMaxLevel - vMinLevel) * 19);
494 ---------------------------------------------------------------------------
496 ---------------------------------------------------------------------------
499 qx.Proto.dispose = function()
501 if (this.getDisposed()) {
505 if (this._indentObject)
507 this._indentObject.dispose();
508 this._indentObject = null;
511 if (this._iconObject)
513 this._iconObject.dispose();
514 this._iconObject = null;
517 if (this._labelObject)
519 this._labelObject.dispose();
520 this._labelObject = null;
523 this._previousParentFolder = null;
525 this.removeEventListener("mousedown", this._onmousedown);
526 this.removeEventListener("mouseup", this._onmouseup);
528 return qx.ui.layout.BoxLayout.prototype.dispose.call(this);