1 /* ************************************************************************
3 qooxdoo - the new era of web development
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.
16 * Derrell Lipman (derrell)
17 * David Perez Carmona (david-perez)
19 ************************************************************************ */
21 /* ************************************************************************
23 #require(qx.theme.Modern)
24 #require(qx.theme.Classic)
25 #require(qx.log.Logger)
27 ************************************************************************ */
30 * A data cell renderer for the tree column of a simple tree
32 qx
.Class
.define("org.argeo.ria.util.TreeDataCellRenderer",
34 extend
: qx
.ui
.treevirtual
.SimpleTreeDataCellRenderer
,
37 construct : function()
41 this.__am
= qx
.util
.AliasManager
.getInstance();
42 this.__rm
= qx
.util
.ResourceManager
;
43 this.__tm
= qx
.theme
.manager
.Appearance
.getInstance();
45 // Base URL used for indentation
46 this.BLANK
= this.__rm
.toUri(this.__am
.resolve("static/blank.gif"));
59 *****************************************************************************
61 *****************************************************************************
67 _getCellStyle : function(cellInfo
)
69 var node
= cellInfo
.value
;
71 // Return the style for the div for the cell. If there's cell-specific
72 // style information provided, append it.
74 this.base(arguments
, cellInfo
) +
75 (node
.cellStyle
? node
.cellStyle
+ ";" : "");
80 _getContentHtml : function(cellInfo
)
84 // Horizontal position
87 // If needed, add extra content before indentation
88 var extra
= this._addExtraContentBeforeIndentation(cellInfo
, pos
);
92 // Add the indentation (optionally with tree lines)
93 var indentation
= this._addIndentation(cellInfo
, pos
);
94 html
+= indentation
.html
95 pos
= indentation
.pos
;
97 // If needed, add extra content before icon
98 extra
= this._addExtraContentBeforeIcon(cellInfo
, pos
);
103 var icon
= this._addIcon(cellInfo
, pos
);
107 // If needed, add extra content before label
108 extra
= this._addExtraContentBeforeLabel(cellInfo
, pos
);
112 // Add the node's label
113 html
+= this._addLabel(cellInfo
, pos
);
119 * Add an image to the tree. This might be a visible icon or it may be
120 * part of the indentation.
122 * @param imageInfo {Map}
123 * How to display the image. It optionally includes any of the
126 * <dt>position {Map}</dt>
128 * If provided, a div is created to hold the image. The div's top,
129 * right, bottom, left, width, and/or height may be specified with
130 * members of this map. Each is expected to be an integer value.
132 * <dt>imageWidth, imageHeight</dt>
134 * The image's width and height. These are used only if both are
140 * The html for this image, possibly with a surrounding div (see
141 * 'position', above).
143 _addImage : function(imageInfo
)
148 var source
= this.__rm
.toUri(this.__am
.resolve(imageInfo
.url
));
150 // If we've been given positioning attributes, enclose image in a div
151 if (imageInfo
.position
)
153 var pos
= imageInfo
.position
;
155 html
.push('<div style="position:absolute;');
157 if (!qx
.core
.Variant
.isSet("qx.client", "mshtml"))
159 html
.push(qx
.bom
.element
.BoxSizing
.compile("content-box"));
162 if (pos
.top
!== undefined)
164 html
.push('top:' + pos
.top
+ 'px;');
167 if (pos
.right
!== undefined)
169 html
.push('right:' + pos
.right
+ 'px;');
172 if (pos
.bottom
!== undefined)
174 html
.push('bottom:' + pos
.bottom
+ 'px;');
177 if (pos
.left
!== undefined)
179 html
.push('left:' + pos
.left
+ 'px;');
182 if (pos
.width
!== undefined)
184 html
.push('width:' + pos
.width
+ 'px;');
187 if (pos
.height
!== undefined)
189 html
.push('height:' + pos
.height
+ 'px;');
195 // Don't use an image tag. They render differently in Firefox and IE7
196 // even if both are enclosed in a div specified as content box. Instead,
197 // add the image as the background image of a div.
198 html
.push('<div style="');
199 html
.push('background-image:url(' + source
+ ');');
200 html
.push('background-repeat:no-repeat;');
202 if (imageInfo
.imageWidth
&& imageInfo
.imageHeight
)
206 imageInfo
.imageWidth
+
209 imageInfo
.imageHeight
+
213 var tooltip
= imageInfo
.tooltip
;
217 html
.push('" title="' + tooltip
);
220 html
.push('"> </div>');
222 if (imageInfo
.position
)
227 return html
.join("");
232 * Add the indentation for this node of the tree.
234 * The indentation optionally includes tree lines. Whether tree lines are
235 * used depends on (a) the properties 'useTreeLines' and
236 * 'excludeFirstLevelTreelines' within this class; and (b) the widget
237 * theme in use (some themes don't support tree lines).
239 * @param cellInfo {Map} The information about the cell.
240 * See {@link qx.ui.table.cellrenderer.Abstract#createDataCellHtml}.
242 * @param pos {Integer}
243 * The position from the left edge of the column at which to render this
247 * The returned map contains an 'html' member which contains the html for
248 * the indentation, and a 'pos' member which is the starting position
249 * plus the width of the indentation.
251 _addIndentation : function(cellInfo
, pos
)
253 var node
= cellInfo
.value
;
257 // Generate the indentation. Obtain icon determination values once
258 // rather than each time through the loop.
259 var bUseTreeLines
= this.getUseTreeLines();
260 var bExcludeFirstLevelTreeLines
= this.getExcludeFirstLevelTreeLines();
261 var bAlwaysShowOpenCloseSymbol
= this.getAlwaysShowOpenCloseSymbol();
263 for (var i
=0; i
<node
.level
; i
++)
265 imageData
= this._getIndentSymbol(i
, node
, bUseTreeLines
,
266 bAlwaysShowOpenCloseSymbol
,
267 bExcludeFirstLevelTreeLines
);
269 html
+= this._addImage(
271 url
: imageData
.icon
,
274 top
: 0 + (imageData
.paddingTop
|| 5),
275 left
: pos
+ (imageData
.paddingLeft
|| 3),
291 * Add the icon for this node of the tree.
293 * @param cellInfo {Map} The information about the cell.
294 * See {@link qx.ui.table.cellrenderer.Abstract#createDataCellHtml}.
296 * @param pos {Integer}
297 * The position from the left edge of the column at which to render this
301 * The returned map contains an 'html' member which contains the html for
302 * the icon, and a 'pos' member which is the starting position plus the
305 _addIcon : function(cellInfo
, pos
)
307 var node
= cellInfo
.value
;
309 // Add the node's icon
310 var imageUrl
= (node
.bSelected
? node
.iconSelected
: node
.icon
);
314 if (node
.type
== qx
.ui
.treevirtual
.SimpleTreeDataModel
.Type
.LEAF
)
316 var o
= this.__tm
.styleFrom("treevirtual-file");
320 var states
= { opened
: node
.bOpened
};
321 var o
= this.__tm
.styleFrom("treevirtual-folder", states
);
327 var html
= this._addImage(
347 * Add the label for this node of the tree.
349 * @param cellInfo {Map} The information about the cell.
350 * See {@link qx.ui.table.cellrenderer.Abstract#createDataCellHtml}.
351 * Additionally, if defined, the labelSpanStyle member is used to apply
352 * style to the span containing the label. (This member is for use by
353 * subclasses; it's not otherwise used by this class.)
355 * @param pos {Integer}
356 * The position from the left edge of the column at which to render this
360 * The html for the label.
362 _addLabel : function(cellInfo
, pos
)
364 var node
= cellInfo
.value
;
366 // Add the node's label. We calculate the "left" property with: each
367 // tree line (indentation) icon is 19 pixels wide; the folder icon is 16
368 // pixels wide, there are two pixels of padding at the left, and we want
369 // 2 pixels between the folder icon and the label
371 '<div style="position:absolute;' +
372 'left:' + pos
+ 'px;' +
374 (node
.labelStyle
? node
.labelStyle
+ ";" : "") +
376 '<span' + (cellInfo
.labelSpanStyle
377 ? 'style="' + cellInfo
.labelSpanStyle
+ ';"'
387 * Adds extra content just before the indentation.
389 * @param cellInfo {Map} The information about the cell.
390 * See {@link qx.ui.table.cellrenderer.Abstract#createDataCellHtml}.
392 * @param pos {Integer}
393 * The position from the left edge of the column at which to render this
397 * The returned map contains an 'html' member which contains the html for
398 * the indentation, and a 'pos' member which is the starting position
399 * plus the width of the indentation.
401 _addExtraContentBeforeIndentation : function(cellInfo
, pos
)
403 return { html
: '', pos
: pos
};
407 * Adds extra content just before the icon.
409 * @param cellInfo {Map} The information about the cell.
410 * See {@link qx.ui.table.cellrenderer.Abstract#createDataCellHtml}.
412 * @param pos {Integer}
413 * The position from the left edge of the column at which to render this
417 * The returned map contains an 'html' member which contains the html for
418 * the indentation, and a 'pos' member which is the starting position
419 * plus the width of the indentation.
421 _addExtraContentBeforeIcon : function(cellInfo
, pos
)
423 return { html
: '', pos
: pos
};
427 * Adds extra content just before the label.
429 * @param cellInfo {Map} The information about the cell.
430 * See {@link qx.ui.table.cellrenderer.Abstract#createDataCellHtml}.
432 * @param pos {Integer}
433 * The position from the left edge of the column at which to render this
437 * The returned map contains an 'html' member which contains the html for
438 * the indentation, and a 'pos' member which is the starting position
439 * plus the width of the indentation.
441 _addExtraContentBeforeLabel : function(cellInfo
, pos
)
443 return { html
: '', pos
: pos
};
448 * Determine the symbol to use for indentation of a tree row, at a
449 * particular column. The indentation to use may be just white space or
450 * may be a tree line. Tree lines come in numerous varieties, so the
451 * appropriate one is selected.
455 * @param column {Integer}
456 * The column of indentation being requested, zero-relative
459 * The node being displayed in the row. The properties of a node are
460 * described in {@link qx.ui.treevirtual.SimpleTreeDataModel}
462 * @param bUseTreeLines {Boolean}
463 * Whether to find an appropriate tree line icon, or simply provide
466 * @param bAlwaysShowOpenCloseSymbol {Boolean}
467 * Whether to display the open/close icon for a node even if it has no
470 * @param bExcludeFirstLevelTreeLines {Boolean}
471 * If bUseTreeLines is enabled, then further filtering of the left-most
472 * tree line may be specified here. If <i>true</i> then the left-most
473 * tree line, between top-level siblings, will not be displayed.
474 * If <i>false</i>, then the left-most tree line wiill be displayed
475 * just like all of the other tree lines.
477 * @return {var} TODOC
479 _getIndentSymbol : function(column
,
482 bAlwaysShowOpenCloseSymbol
,
483 bExcludeFirstLevelTreeLines
)
485 var STDCR
= org
.argeo
.ria
.util
.TreeDataCellRenderer
;
487 // If we're in column 0 and excludeFirstLevelTreeLines is enabled, then
488 // we treat this as if no tree lines were requested.
489 if (column
== 0 && bExcludeFirstLevelTreeLines
)
491 bUseTreeLines
= false;
494 // If we're not on the final column...
495 if (column
< node
.level
- 1)
497 // then return either a line or a blank icon, depending on
499 return (bUseTreeLines
&& ! node
.lastChild
[column
]
501 : { icon
: this.BLANK
});
504 var bLastChild
= node
.lastChild
[node
.lastChild
.length
- 1];
506 // Is this a branch node that does not have the open/close button hidden?
507 if (node
.type
== qx
.ui
.treevirtual
.SimpleTreeDataModel
.Type
.BRANCH
&&
508 ! node
.bHideOpenClose
)
510 // Does this node have any children, or do we always want the
511 // open/close symbol to be shown?
512 if (node
.children
.length
> 0 || bAlwaysShowOpenCloseSymbol
)
514 // If we're not showing tree lines...
517 // ... then just use a expand or contract
519 ? STDCR
.__icon
.contract
520 : STDCR
.__icon
.expand
);
523 // Are we looking at a top-level, first child of its parent?
524 if (column
== 0 && node
.bFirstChild
)
526 // Yup. If it's also a last child...
529 // ... then use no tree lines.
531 ? STDCR
.__icon
.onlyContract
532 : STDCR
.__icon
.onlyExpand
);
536 // otherwise, use descender lines but no ascender.
538 ? STDCR
.__icon
.startContract
539 : STDCR
.__icon
.startExpand
);
543 // It's not a top-level, first child. Is this the last child of its
547 // Yup. Return an ending expand or contract.
549 ? STDCR
.__icon
.endContract
550 : STDCR
.__icon
.endExpand
);
553 // Otherwise, return a crossing expand or contract.
555 ? STDCR
.__icon
.crossContract
556 : STDCR
.__icon
.crossExpand
);
560 // This node does not have any children. Return an end or cross, if
561 // we're using tree lines.
564 // If this is a child of the root node...
565 if (node
.parentNodeId
== 0)
567 // If this is the only child...
568 if (bLastChild
&& node
.bFirstChild
)
570 // ... then return a blank.
571 return { icon
: this.BLANK
};
574 // Otherwise, if this is the last child...
577 // ... then return an end line.
578 return STDCR
.__icon
.end
;
581 // Otherwise if this is the first child...
582 if (node
.bFirstChild
)
584 // ... then return a start line.
585 return STDCR
.__icon
.startContract
;
589 // If this is a last child, return and ending line; otherwise cross.
592 : STDCR
.__icon
.cross
);
595 return { icon
: this.BLANK
};
601 // Ensure that the theme is initialized
602 qx
.theme
.manager
.Meta
.getInstance().initialize();
604 var STDCR
= org
.argeo
.ria
.util
.TreeDataCellRenderer
;
606 var ImageLoader
= qx
.io2
.ImageLoader
;
608 var am
= qx
.util
.AliasManager
.getInstance();
609 var rm
= qx
.util
.ResourceManager
;
610 var tm
= qx
.theme
.manager
.Appearance
.getInstance();
612 var loadImage = function(f
)
614 ImageLoader
.load(rm
.toUri(am
.resolve(f
)));
617 STDCR
.__icon
.line
= tm
.styleFrom("treevirtual-line");
618 loadImage(STDCR
.__icon
.line
.icon
);
620 STDCR
.__icon
.contract
= tm
.styleFrom("treevirtual-contract");
621 loadImage(STDCR
.__icon
.contract
.icon
);
623 STDCR
.__icon
.expand
= tm
.styleFrom("treevirtual-expand");
624 loadImage(STDCR
.__icon
.expand
.icon
);
626 STDCR
.__icon
.onlyContract
= tm
.styleFrom("treevirtual-only-contract");
627 loadImage(STDCR
.__icon
.onlyContract
.icon
);
629 STDCR
.__icon
.onlyExpand
= tm
.styleFrom("treevirtual-only-expand");
630 loadImage(STDCR
.__icon
.onlyExpand
.icon
);
632 STDCR
.__icon
.startContract
= tm
.styleFrom("treevirtual-start-contract");
633 loadImage(STDCR
.__icon
.startContract
.icon
);
635 STDCR
.__icon
.startExpand
= tm
.styleFrom("treevirtual-start-expand");
636 loadImage(STDCR
.__icon
.startExpand
.icon
);
638 STDCR
.__icon
.endContract
= tm
.styleFrom("treevirtual-end-contract");
639 loadImage(STDCR
.__icon
.endContract
.icon
);
641 STDCR
.__icon
.endExpand
= tm
.styleFrom("treevirtual-end-expand");
642 loadImage(STDCR
.__icon
.endExpand
.icon
);
644 STDCR
.__icon
.crossContract
= tm
.styleFrom("treevirtual-cross-contract");
645 loadImage(STDCR
.__icon
.crossContract
.icon
);
647 STDCR
.__icon
.crossExpand
= tm
.styleFrom("treevirtual-cross-expand");
648 loadImage(STDCR
.__icon
.crossExpand
.icon
);
650 STDCR
.__icon
.end
= tm
.styleFrom("treevirtual-end");
651 loadImage(STDCR
.__icon
.end
.icon
);
653 STDCR
.__icon
.cross
= tm
.styleFrom("treevirtual-cross");
654 loadImage(STDCR
.__icon
.cross
.icon
);
657 destruct : function()