KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > icesoft > faces > component > tree > TreeRenderer


1 /*
2  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
3  *
4  * "The contents of this file are subject to the Mozilla Public License
5  * Version 1.1 (the "License"); you may not use this file except in
6  * compliance with the License. You may obtain a copy of the License at
7  * http://www.mozilla.org/MPL/
8  *
9  * Software distributed under the License is distributed on an "AS IS"
10  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
11  * License for the specific language governing rights and limitations under
12  * the License.
13  *
14  * The Original Code is ICEfaces 1.5 open source software code, released
15  * November 5, 2006. The Initial Developer of the Original Code is ICEsoft
16  * Technologies Canada, Corp. Portions created by ICEsoft are Copyright (C)
17  * 2004-2006 ICEsoft Technologies Canada, Corp. All Rights Reserved.
18  *
19  * Contributor(s): _____________________.
20  *
21  * Alternatively, the contents of this file may be used under the terms of
22  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"
23  * License), in which case the provisions of the LGPL License are
24  * applicable instead of those above. If you wish to allow use of your
25  * version of this file only under the terms of the LGPL License and not to
26  * allow others to use your version of this file under the MPL, indicate
27  * your decision by deleting the provisions above and replace them with
28  * the notice and other provisions required by the LGPL License. If you do
29  * not delete the provisions above, a recipient may use your version of
30  * this file under either the MPL or the LGPL License."
31  *
32  */

33
34 package com.icesoft.faces.component.tree;
35
36 import com.icesoft.faces.component.CSS_DEFAULT;
37 import com.icesoft.faces.component.InvalidComponentTypeException;
38 import com.icesoft.faces.component.ext.taglib.Util;
39 import com.icesoft.faces.component.util.CustomComponentUtils;
40 import com.icesoft.faces.context.DOMContext;
41 import com.icesoft.faces.renderkit.dom_html_basic.DomBasicRenderer;
42 import com.icesoft.faces.renderkit.dom_html_basic.FormRenderer;
43 import com.icesoft.faces.renderkit.dom_html_basic.HTML;
44 import com.icesoft.faces.renderkit.dom_html_basic.PassThruAttributeRenderer;
45 import com.icesoft.faces.util.CoreUtils;
46
47 import org.w3c.dom.Element JavaDoc;
48
49 import javax.faces.component.UIComponent;
50 import javax.faces.context.FacesContext;
51 import javax.faces.event.ActionEvent;
52 import javax.swing.tree.DefaultMutableTreeNode JavaDoc;
53 import javax.swing.tree.TreeModel JavaDoc;
54 import java.io.IOException JavaDoc;
55 import java.util.Map JavaDoc;
56
57 /**
58  * TreeRenderer is an ICEfaces D2D renderer for the Tree component.
59  *
60  * @author gmccleary
61  * @version 1.1
62  */

63 public class TreeRenderer extends DomBasicRenderer {
64
65     /**
66      *
67      */

68     public static final String JavaDoc PATH_DELIMITER = "-";
69
70     /**
71      * @return true as this component will render its children.
72      */

73     public boolean getRendersChildren() {
74         return true;
75     }
76
77     /**
78      * @param facesContext
79      * @param uiComponent
80      */

81     public void decode(FacesContext facesContext, UIComponent uiComponent) {
82         if (isStatic(uiComponent)) {
83             return;
84         }
85
86         Tree treeComponent = (Tree) uiComponent;
87         String JavaDoc expandNodeKey = CustomComponentUtils
88                 .getHiddenTreeExpandFieldName(
89                         uiComponent.getClientId(facesContext),
90                         CustomComponentUtils.getFormName(uiComponent,
91                                                          facesContext));
92         String JavaDoc pathToExpandedNode = (String JavaDoc) facesContext.getExternalContext()
93                 .getRequestParameterMap().get(expandNodeKey);
94         // handle navigation: if the user clicked on an open/close icon
95
// then expand/contract the appropriate node by updating the state
96
// of the user object encapsulated by the tree node that was expanded/collapsed
97
if (pathToExpandedNode != null &&
98             !pathToExpandedNode.equalsIgnoreCase("")) {
99             try {
100                 // get the node that was expanded/contracted
101
DefaultMutableTreeNode JavaDoc navigatedNode =
102                         treeComponent.getNodeAtPathsEnd(pathToExpandedNode);
103                 treeComponent.setNavigatedNode(navigatedNode);
104                 IceUserObject userObject =
105                         (IceUserObject) navigatedNode.getUserObject();
106                 if (userObject != null) {
107                     treeComponent.setNavigationEventType(
108                             userObject.isExpanded() ?
109                             Tree.NAVIGATION_EVENT_COLLAPSE :
110                             Tree.NAVIGATION_EVENT_EXPAND);
111                     userObject.setExpanded(!userObject.isExpanded());
112                 }
113
114                 ActionEvent actionEvent = new ActionEvent(uiComponent);
115                 uiComponent.queueEvent(actionEvent);
116
117             } catch (NumberFormatException JavaDoc nfe) {
118                 throw new InvalidNavigationId(
119                         "TreeRenderer.decode() NumberFormatException invalid tree navigation id",
120                         nfe);
121             }
122         }
123     }
124
125     /**
126      * @param facesContext
127      * @param uiComponent
128      * @throws IOException
129      */

130     public void encodeBegin(FacesContext facesContext, UIComponent uiComponent)
131             throws IOException JavaDoc {
132
133         // get domContext first, to check if we are stream writing
134
DOMContext domContext =
135                 DOMContext.attachDOMContext(facesContext, uiComponent);
136
137         // setup
138
validateParameters(facesContext, uiComponent, Tree.class);
139
140         Tree treeComponent = (Tree) uiComponent;
141         TreeModel JavaDoc treeModel = (TreeModel JavaDoc) uiComponent
142                 .getValueBinding("value").getValue(facesContext);
143
144         if (treeComponent.getChildCount() != 1) {
145             throw new MalformedTreeTagException(
146                     "The tree tag requires a single child treeNode tag. Found [" +
147                     treeComponent.getChildCount() + "]");
148         }
149
150         if (treeModel == null) {
151             return;
152         }
153
154         // set up form fields
155
FormRenderer.addHiddenField(facesContext,
156                                     CustomComponentUtils.getHiddenTreeExpandFieldName(
157                                             uiComponent.getClientId(
158                                                     facesContext),
159                                             CustomComponentUtils.getFormName(
160                                                     uiComponent,
161                                                     facesContext)));
162         FormRenderer.addHiddenField(facesContext,
163                                     CustomComponentUtils.getHiddenTreeActionFieldName(
164                                             uiComponent.getClientId(
165                                                     facesContext),
166                                             CustomComponentUtils.getFormName(
167                                                     uiComponent,
168                                                     facesContext)));
169
170         // encode the root DIV
171
if (!domContext.isInitialized()) {
172             Element JavaDoc rootDOMNode = domContext.createRootElement(HTML.DIV_ELEM);
173             rootDOMNode.setAttribute(HTML.ID_ATTR,
174                                      uiComponent.getClientId(facesContext));
175         }
176         // get the root node
177
Element JavaDoc rootDomNode = (Element JavaDoc) domContext.getRootNode();
178
179         // Apply default styleClass and style to the root node.
180
rootDomNode
181                 .setAttribute(HTML.CLASS_ATTR, treeComponent.getStyleClass());
182         String JavaDoc style = treeComponent.getStyle();
183         if(style != null && style.length() > 0)
184             rootDomNode.setAttribute(HTML.STYLE_ATTR, style);
185         else
186             rootDomNode.removeAttribute(HTML.STYLE_ATTR);
187
188         // clean up, and remove nodes
189
DOMContext.removeChildren(rootDomNode);
190
191         if (PassThruAttributeRenderer.passThruAttributeExists(uiComponent)) {
192             PassThruAttributeRenderer
193                     .renderAttributes(facesContext, uiComponent, null);
194         }
195
196         // startNode is used in conjunction with endNode as an alternative to streamWrite method
197
domContext.startNode(facesContext, treeComponent, rootDomNode);
198
199         domContext.stepInto(uiComponent);
200
201     }
202
203     private boolean isHideRootNode(Tree treeComponent) {
204         String JavaDoc hideRootNodeAttribute =
205                 (String JavaDoc) treeComponent.getAttributes().get("hideRootNode");
206         return hideRootNodeAttribute != null &&
207                hideRootNodeAttribute.equalsIgnoreCase("true");
208     }
209
210     private boolean isHideNavigation(Tree treeComponent) {
211         String JavaDoc hideNavAttr =
212                 (String JavaDoc) treeComponent.getAttributes().get("hideNavigation");
213         return hideNavAttr != null && hideNavAttr.equalsIgnoreCase("true");
214     }
215
216     /**
217      * @param facesContext
218      * @param uiComponent
219      * @throws IOException
220      */

221     public void encodeChildren(FacesContext facesContext,
222                                UIComponent uiComponent)
223             throws IOException JavaDoc {
224
225         // get domContext first to check if we are stream writing
226
DOMContext domContext =
227                 DOMContext.getDOMContext(facesContext, uiComponent);
228
229         TreeModel JavaDoc treeModel = (TreeModel JavaDoc) uiComponent
230                 .getValueBinding("value").getValue(facesContext);
231         DefaultMutableTreeNode JavaDoc treeComponentRootNode =
232                 (DefaultMutableTreeNode JavaDoc) treeModel.getRoot();
233         Element JavaDoc rootNode = (Element JavaDoc) domContext.getRootNode();
234         com.icesoft.faces.component.tree.TreeNode treeNode =
235                 (TreeNode) (uiComponent).getChildren().get(0);
236         boolean hideRootNode;
237         if (uiComponent instanceof Tree) {
238             hideRootNode = isHideRootNode((Tree) uiComponent);
239         } else {
240             throw new InvalidComponentTypeException("Expecting a Tree");
241         }
242
243         encodeParentAndChildNodes(facesContext, (Tree) uiComponent,
244                                   (DefaultMutableTreeNode JavaDoc) treeModel.getRoot(),
245                                   hideRootNode, rootNode, treeComponentRootNode,
246                                   treeNode);
247
248     }
249
250     /**
251      * @param facesContext
252      * @param treeComponent
253      * @param current
254      * @param hideCurrentNode
255      * @param parentDOMNode
256      * @param treeComponentRootNode
257      * @param treeNode
258      */

259     public void encodeParentAndChildNodes(FacesContext facesContext,
260                                           Tree treeComponent,
261                                           DefaultMutableTreeNode JavaDoc current,
262                                           boolean hideCurrentNode,
263                                           Element JavaDoc parentDOMNode,
264                                           DefaultMutableTreeNode JavaDoc treeComponentRootNode,
265                                           TreeNode treeNode) {
266
267         DOMContext domContext =
268                 DOMContext.getDOMContext(facesContext, treeComponent);
269
270         Element JavaDoc treeNodeDiv = domContext.createElement(HTML.DIV_ELEM);
271         if (!hideCurrentNode) {
272             // put the next node on the request map
273
Map JavaDoc requestMap = facesContext.getExternalContext().getRequestMap();
274             String JavaDoc varAttribute = treeComponent.getVar();
275             requestMap.put(varAttribute, current);
276             domContext.setCursorParent(parentDOMNode);
277
278             treeNodeDiv.setAttribute(HTML.NAME_ATTR, "treeNodeDiv");
279             treeNodeDiv
280                     .setAttribute(HTML.CLASS_ATTR, treeComponent.getTreeRowStyleClass());
281             parentDOMNode.appendChild(treeNodeDiv);
282             domContext.setCursorParent(treeNodeDiv);
283             // startNode is used in conjunction with endNode as an alternative to streamWrite method
284
try {
285                 domContext.startNode(facesContext, treeComponent, treeNodeDiv);
286             } catch (IOException JavaDoc ioe) {
287                 ioe.printStackTrace();
288             }
289
290             encodeNode(facesContext, treeComponent, current, treeNodeDiv,
291                        domContext, treeComponentRootNode, treeNode,
292                        parentDOMNode);
293
294         } else {
295             // root node is hidden
296
// put the next node on the request map
297
Map JavaDoc requestMap = facesContext.getExternalContext().getRequestMap();
298             String JavaDoc varAttribute = treeComponent.getVar();
299             requestMap.put(varAttribute, current);
300             domContext.setCursorParent(parentDOMNode);
301
302             treeNodeDiv.setAttribute(HTML.NAME_ATTR, "treeNodeDiv");
303             treeNodeDiv
304                     .setAttribute(HTML.CLASS_ATTR, treeComponent.getTreeRowStyleClass());
305             // treeNodeDiv id is assigned here when roo node is hidden
306
treeNodeDiv.setAttribute(HTML.ID_ATTR, treeComponent
307                     .getClientId(facesContext) + "-div-root");
308             parentDOMNode.appendChild(treeNodeDiv);
309             domContext.setCursorParent(treeNodeDiv);
310             // startNode is used in conjunction with endNode as an alternative to streamWrite method
311
try {
312                 domContext.startNode(facesContext, treeComponent, treeNodeDiv);
313             } catch (IOException JavaDoc ioe) {
314                 ioe.printStackTrace();
315             }
316                        
317         }
318         // iterate child nodes
319
int childCount = current.getChildCount();
320         if (childCount > 0 &&
321             ((IceUserObject) current.getUserObject()).isExpanded()) {
322             // render CHILD div
323
Element JavaDoc childDiv = domContext.createElement(HTML.DIV_ELEM);
324             childDiv.setAttribute(HTML.NAME_ATTR, "CHILD");
325             childDiv.setAttribute(HTML.ID_ATTR, treeNodeDiv
326                     .getAttribute(HTML.ID_ATTR) + "-child");
327
328             treeNodeDiv.appendChild(childDiv);
329             
330             // this method is used in conjunction with endNode as an alternative to streamWrite method
331
try {
332                 domContext.startNode(facesContext, treeComponent, childDiv);
333             } catch (IOException JavaDoc ioe) {
334                 ioe.printStackTrace();
335             }
336
337             // recurse children
338
DefaultMutableTreeNode JavaDoc next;
339             for (int i = 0; i < childCount; i++) {
340                 next = (DefaultMutableTreeNode JavaDoc) current.getChildAt(i);
341                 encodeParentAndChildNodes(facesContext, treeComponent, next,
342                                           false, childDiv,
343                                           treeComponentRootNode, treeNode);
344             }
345             // endNode is used in conjunction with startNode as an alternative to streamWrite method
346
try {
347                 domContext.endNode(facesContext, treeComponent, childDiv);
348             } catch (IOException JavaDoc ioe) {
349                 ioe.printStackTrace();
350             }
351
352         }
353
354     }
355
356     /**
357      * @param facesContext
358      * @param treeComponent
359      * @param currentNode
360      * @param treeNodeDiv
361      * @param domContext
362      * @param treeComponentRootNode
363      * @param treeNode
364      * @param parentDOMNode
365      */

366     public void encodeNode(FacesContext facesContext,
367                            Tree treeComponent,
368                            DefaultMutableTreeNode JavaDoc currentNode,
369                            Element JavaDoc treeNodeDiv,
370                            DOMContext domContext,
371                            DefaultMutableTreeNode JavaDoc treeComponentRootNode,
372                            TreeNode treeNode,
373                            Element JavaDoc parentDOMNode) {
374
375         String JavaDoc pathToCurrentRoot =
376                 getPathAsString(currentNode, treeComponentRootNode);
377         boolean hideRootNode = isHideRootNode(treeComponent);
378         boolean hideNavigation = isHideNavigation(treeComponent);
379
380         treeNode.setMutable(currentNode);
381         treeNode.setId(Tree.ID_PREFIX + pathToCurrentRoot);
382         treeNode.setParent(treeComponent);
383
384         // efficiency and simplicity
385
IceUserObject userObject = (IceUserObject) currentNode.getUserObject();
386         // a branch node is a node that is not a leaf
387
boolean isBranchNode = !userObject.isLeaf();
388         boolean isExpanded = userObject.isExpanded();
389         boolean isLastChild =
390                 treeComponentRootNode.getLastLeaf() == currentNode;
391         boolean isCollapsedAndFinalBranch = false;
392         if (isBranchNode && !isExpanded) {
393             isCollapsedAndFinalBranch = isCollapsedAndFinalBranch(currentNode);
394         }
395         int level = currentNode.getLevel();
396         UIComponent myForm = findForm(treeComponent);
397         String JavaDoc formId = myForm.getClientId(facesContext);
398
399         // if the root node was not rendered, then don't render the first
400
// column of lines extending down from the position where the root
401
// node would have been
402
if (hideRootNode) {
403             level--;
404         }
405         for (int i = 0; i < level; i++) {
406             //render the vertical line or blank
407
Element JavaDoc verticalLine = domContext.createElement(HTML.IMG_ELEM);
408             verticalLine.setAttribute(HTML.ALT_ATTR, "");
409
410             // use the level to check parentNodes
411
// to determine if we render a line or a blank
412
DefaultMutableTreeNode JavaDoc parentNode = null;
413             if ((i > 0) || (hideRootNode)) {
414                 // start at 1 because we are making a call to getParent first
415
int j = 1;
416                 parentNode = (DefaultMutableTreeNode JavaDoc) currentNode.getParent();
417                 while (j < (level - i)) {
418                     parentNode =
419                             (DefaultMutableTreeNode JavaDoc) parentNode.getParent();
420                     j++;
421                 }
422             }
423
424             boolean renderBlank = false;
425
426             if ((null != parentNode) && (parentNode.getNextSibling() == null)) {
427                 renderBlank = true;
428             }
429
430             if (renderBlank) {
431                 verticalLine.setAttribute(HTML.SRC_ATTR,
432                                           treeComponent.getLineBlankImage());
433             } else if ((i == 0) && (!hideRootNode)) {
434                 verticalLine.setAttribute(HTML.SRC_ATTR,
435                                           treeComponent.getLineBlankImage());
436             } else if (isLastChild || isCollapsedAndFinalBranch) {
437                 verticalLine.setAttribute(HTML.SRC_ATTR,
438                                           treeComponent.getLineBottomImage());
439             } else {
440                 verticalLine.setAttribute(HTML.SRC_ATTR,
441                                           treeComponent.getLineVerticalImage());
442             }
443
444             verticalLine.setAttribute(HTML.BORDER_ATTR, "0");
445             treeNodeDiv.appendChild(verticalLine);
446             // startNode is used in conjunction with endNode as an alternative to streamWrite method
447
try {
448                 domContext.startNode(facesContext, treeComponent, verticalLine);
449                 domContext.endNode(facesContext, treeComponent, verticalLine);
450             } catch (IOException JavaDoc ioe) {
451                 ioe.printStackTrace();
452             }
453
454         }
455
456         if (isBranchNode && !hideNavigation) {
457             Element JavaDoc navAnchor = domContext.createElement(HTML.ANCHOR_ELEM);
458             navAnchor.setAttribute(HTML.HREF_ATTR, "#");
459             navAnchor.setAttribute(HTML.ID_ATTR,
460                                    formId + ":" + pathToCurrentRoot);
461             navAnchor.setAttribute(HTML.ONFOCUS_ATTR, "setFocus(this.id);");
462             navAnchor.setAttribute(HTML.ONBLUR_ATTR, "setFocus('');");
463             String JavaDoc hiddenFieldName =
464                     CustomComponentUtils.getHiddenTreeExpandFieldName(
465                             treeComponent.getClientId(facesContext),
466                             CustomComponentUtils.getFormName(treeComponent,
467                                                              facesContext));
468
469             String JavaDoc onclickString =
470                     "document.forms['" + formId + "']['" + hiddenFieldName +
471                     "'].value="
472                     + "'" + pathToCurrentRoot + "';"
473                     + "iceSubmitPartial("
474                     + " document.forms['" + formId + "'],"
475                     + " this,event); "
476                     + "return false;";
477
478             navAnchor.setAttribute(HTML.ONCLICK_ATTR, onclickString);
479             treeNodeDiv.appendChild(navAnchor);
480             // icon
481
Element JavaDoc iconImage = domContext.createElement(HTML.IMG_ELEM);
482             // Determine whether to render the top, middle, or bottom image:
483
// Encode the top image with no lines extending if this node is the
484
// root of the tree, has children, and is not expanded.
485
// Also render the top image with no lines extending if the root
486
// node is hidden and this node is the only child of the root and
487
// this node is not expanded.
488
// Encode the top image if this is the root of the entire tree
489
// or if the root is hidden and this is its first child
490
// Encode the bottom image if this node has children,
491
// is the last child of its parent, and is not expanded
492
// Encode the middle image by default
493
// *** cleanup replaced line images with blanks ***
494
if (currentNode.isRoot() && !isExpanded ||
495                 hideRootNode
496                 && currentNode.getNextSibling() == null
497                 && currentNode == treeComponentRootNode.getFirstChild()
498                     ) {
499                 iconImage.setAttribute(HTML.SRC_ATTR,
500                                        treeComponent.getNavOpenTopNoSiblingsImage());
501             } else if (currentNode.isRoot() ||
502                        hideRootNode &&
503                        treeComponentRootNode.getFirstChild() == currentNode) {
504                 if (isExpanded) {
505                     iconImage.setAttribute(HTML.SRC_ATTR,
506                                            treeComponent.getNavCloseTopNoSiblingsImage());
507                 } else {
508                     iconImage.setAttribute(HTML.SRC_ATTR,
509                                            treeComponent.getNavOpenTopNoSiblingsImage());
510                 }
511             } else if (currentNode.getNextSibling() == null
512                        && currentNode.getChildCount() > 0) {
513                 if (isExpanded) {
514                     iconImage.setAttribute(HTML.SRC_ATTR,
515                                            treeComponent.getNavCloseBottomImage());
516                 } else {
517                     iconImage.setAttribute(HTML.SRC_ATTR,
518                                            treeComponent.getNavOpenBottomImage());
519                 }
520             } else {
521                 if (isExpanded) {
522                     iconImage.setAttribute(HTML.SRC_ATTR,
523                                            treeComponent.getNavCloseMiddleImage());
524                 } else {
525                     iconImage.setAttribute(HTML.SRC_ATTR,
526                                            treeComponent.getNavOpenMiddleImage());
527                 }
528             }
529             iconImage.setAttribute(HTML.BORDER_ATTR, "0");
530             iconImage.setAttribute(HTML.ALT_ATTR, "");
531
532             navAnchor.appendChild(iconImage);
533             // use startNode and endNode as an alternative to streamWrite method
534
try {
535                 domContext.startNode(facesContext, treeComponent, navAnchor);
536                 domContext.startNode(facesContext, treeComponent, iconImage);
537                 domContext.endNode(facesContext, treeComponent, iconImage);
538                 domContext.endNode(facesContext, treeComponent, navAnchor);
539             } catch (IOException JavaDoc ioe) {
540                 ioe.printStackTrace();
541             }
542
543         } else { // this is a leaf node
544
Element JavaDoc lineImage = domContext.createElement(HTML.IMG_ELEM);
545             treeNodeDiv.appendChild(lineImage);
546             lineImage.setAttribute(HTML.BORDER_ATTR, "0");
547             lineImage.setAttribute(HTML.ALT_ATTR, "");
548
549             if (currentNode.getNextSibling() == null) {
550                 // use lineBottomNode image
551
lineImage.setAttribute(HTML.SRC_ATTR,
552                                        treeComponent.getLineBottomImage());
553             } else {
554                 // use lineMiddleNode image
555
lineImage.setAttribute(HTML.SRC_ATTR,
556                                        treeComponent.getLineMiddleImage());
557             }
558
559             // use startNode and endNode as an alternative to streamWrite method
560
try {
561                 domContext.startNode(facesContext, treeComponent, lineImage);
562                 domContext.endNode(facesContext, treeComponent, lineImage);
563             } catch (IOException JavaDoc ioe) {
564                 ioe.printStackTrace();
565             }
566         }
567
568         String JavaDoc pathToNode = TreeRenderer.getPathAsString(currentNode,
569                                                          (DefaultMutableTreeNode JavaDoc) treeComponent
570                                                                  .getModel()
571                                                                  .getRoot());
572         treeNodeDiv.setAttribute(HTML.ID_ATTR, treeComponent
573                 .getClientId(facesContext) + "-div-" + pathToNode);
574
575         try {
576             encodeParentAndChildren(facesContext, treeNode);
577         } catch (IOException JavaDoc e) {
578             e.printStackTrace();
579         }
580         // use endNode as an alternative to streamWrite method
581
try {
582             domContext.endNode(facesContext, treeComponent, treeNodeDiv);
583         } catch (IOException JavaDoc ioe) {
584             ioe.printStackTrace();
585         }
586
587     }
588
589     /**
590      * @param facesContext
591      * @param uiComponent
592      * @throws IOException
593      */

594     public void encodeEnd(FacesContext facesContext, UIComponent uiComponent)
595             throws IOException JavaDoc {
596         // TODO refactor
597
// the adding of this hidden div ensures that Firefox loads all the
598
// (default) images for the tree so when a tree node is clicked and the
599
// first instance of an image is encountered for display we don't have to
600
// wait for it to be downloaded. The visual disruption that the downloading
601
// causes is only visible on firefox. Firefox lays out the page first
602
// without the image, and the text in the tree node appears farther left
603
// than it will be after the image is downloaded.
604
// Then, after the image is downloaded,
605
// the page is layed-out again and the text moves to the right
606
// to accomodate the image that has finally arrived.
607
validateParameters(facesContext, uiComponent, Tree.class);
608
609         DOMContext domContext =
610                 DOMContext.getDOMContext(facesContext, uiComponent);
611
612         Element JavaDoc rootNode = (Element JavaDoc) domContext.getRootNode();
613
614         Element JavaDoc imageLoaderDiv = domContext.createElement(HTML.DIV_ELEM);
615         imageLoaderDiv.setAttribute(HTML.ID_ATTR, "imageCache");
616         imageLoaderDiv.setAttribute(HTML.STYLE_ATTR, "display:none;");
617         rootNode.appendChild(imageLoaderDiv);
618
619         Element JavaDoc tree_document = domContext.createElement(HTML.IMG_ELEM);
620         Element JavaDoc tree_line_blank = domContext.createElement(HTML.IMG_ELEM);
621         Element JavaDoc tree_line_vertical = domContext.createElement(HTML.IMG_ELEM);
622         Element JavaDoc tree_nav_middle_close = domContext.createElement(HTML.IMG_ELEM);
623         Element JavaDoc tree_nav_top_open = domContext.createElement(HTML.IMG_ELEM);
624         Element JavaDoc tree_folder_close = domContext.createElement(HTML.IMG_ELEM);
625         Element JavaDoc tree_line_last_node = domContext.createElement(HTML.IMG_ELEM);
626         Element JavaDoc tree_nav_bottom_close = domContext.createElement(HTML.IMG_ELEM);
627         Element JavaDoc tree_nav_middle_open = domContext.createElement(HTML.IMG_ELEM);
628         Element JavaDoc tree_nav_top_open_no_siblings =
629                 domContext.createElement(HTML.IMG_ELEM);
630         Element JavaDoc tree_folder_open = domContext.createElement(HTML.IMG_ELEM);
631         Element JavaDoc tree_line_middle_node = domContext.createElement(HTML.IMG_ELEM);
632         Element JavaDoc tree_nav_bottom_open = domContext.createElement(HTML.IMG_ELEM);
633         Element JavaDoc tree_nav_top_close = domContext.createElement(HTML.IMG_ELEM);
634
635         String JavaDoc appBase = CoreUtils.resolveResourceURL(facesContext, "/xmlhttp/css/xp/css-images/");
636
637         tree_document.setAttribute(HTML.SRC_ATTR, appBase + "tree_document.gif");
638         tree_line_blank.setAttribute(HTML.SRC_ATTR, appBase + "tree_line_blank.gif");
639         tree_line_vertical.setAttribute(HTML.SRC_ATTR, appBase + "tree_line_vertical.gif");
640         tree_nav_middle_close.setAttribute(HTML.SRC_ATTR, appBase + "tree_nav_middle_close.gif");
641         tree_nav_top_open.setAttribute(HTML.SRC_ATTR, appBase + "tree_nav_top_open.gif");
642         tree_folder_close.setAttribute(HTML.SRC_ATTR, appBase + "tree_folder_close.gif");
643         tree_line_last_node.setAttribute(HTML.SRC_ATTR, appBase + "tree_line_last_node.gif");
644         tree_nav_bottom_close.setAttribute(HTML.SRC_ATTR, appBase +
645                                                           "tree_nav_bottom_close.gif");
646         tree_nav_middle_open.setAttribute(HTML.SRC_ATTR, appBase +
647                                                          "tree_nav_middle_open.gif");
648         tree_nav_top_open_no_siblings.setAttribute(HTML.SRC_ATTR, appBase +
649                                                                   "tree_nav_top_open_no_siblings.gif");
650         tree_folder_open.setAttribute(HTML.SRC_ATTR, appBase +
651                                                      "tree_folder_open.gif");
652         tree_line_middle_node.setAttribute(HTML.SRC_ATTR, appBase +
653                                                           "tree_line_middle_node.gif");
654         tree_nav_bottom_open.setAttribute(HTML.SRC_ATTR, appBase +
655                                                          "tree_nav_bottom_open.gif");
656         tree_nav_top_close.setAttribute(HTML.SRC_ATTR, appBase +
657                                                        "tree_nav_top_close.gif");
658
659         imageLoaderDiv.appendChild(tree_document);
660         imageLoaderDiv.appendChild(tree_line_blank);
661         imageLoaderDiv.appendChild(tree_line_vertical);
662         imageLoaderDiv.appendChild(tree_nav_middle_close);
663         imageLoaderDiv.appendChild(tree_nav_top_open);
664         imageLoaderDiv.appendChild(tree_folder_close);
665         imageLoaderDiv.appendChild(tree_line_last_node);
666         imageLoaderDiv.appendChild(tree_nav_bottom_close);
667         imageLoaderDiv.appendChild(tree_nav_middle_open);
668         imageLoaderDiv.appendChild(tree_nav_top_open_no_siblings);
669         imageLoaderDiv.appendChild(tree_folder_open);
670         imageLoaderDiv.appendChild(tree_line_middle_node);
671         imageLoaderDiv.appendChild(tree_nav_bottom_open);
672         imageLoaderDiv.appendChild(tree_nav_top_close);
673
674         // use endNode as an alternative to streamWrite method
675
// close the root node
676
domContext.endNode(facesContext, uiComponent, rootNode);
677
678         domContext.stepOver();
679     }
680
681     private boolean isCollapsedAndFinalBranch(DefaultMutableTreeNode JavaDoc branch) {
682         javax.swing.tree.TreeNode JavaDoc[] path = branch.getPath();
683         for (int i = 0; i + 1 < path.length; i++) {
684             DefaultMutableTreeNode JavaDoc nextParent =
685                     (DefaultMutableTreeNode JavaDoc) path[i];
686             DefaultMutableTreeNode JavaDoc nextChild =
687                     (DefaultMutableTreeNode JavaDoc) path[i + 1];
688             if (!(nextParent.getLastChild() == nextChild)) {
689                 return false;
690             }
691         }
692         return true;
693     }
694
695     /**
696      * @param currentRoot
697      * @param treeComponentRootNode
698      * @return the path to the given currentRoot
699      */

700     public static String JavaDoc getPathAsString(DefaultMutableTreeNode JavaDoc currentRoot,
701                                          DefaultMutableTreeNode JavaDoc treeComponentRootNode) {
702         if (currentRoot == treeComponentRootNode) {
703             // special case since there is no path to the root node
704
return "root";
705         }
706         StringBuffer JavaDoc convertedPath = new StringBuffer JavaDoc();
707         javax.swing.tree.TreeNode JavaDoc[] path = currentRoot.getPath();
708         int pathLength = path.length;
709         javax.swing.tree.TreeNode JavaDoc parent = treeComponentRootNode;
710         for (int i = 1; i < pathLength; i++) {
711             javax.swing.tree.TreeNode JavaDoc nextNodeInPath = path[i];
712             int indexOfNextNodeInPath = parent.getIndex(nextNodeInPath);
713             convertedPath.append(indexOfNextNodeInPath);
714             if (i + 1 < pathLength) {
715                 convertedPath.append(PATH_DELIMITER);
716             }
717             parent = nextNodeInPath;
718         }
719         return convertedPath.toString();
720     }
721 }
722
Popular Tags