View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.myfaces.custom.tree.renderkit.html;
20  
21  import java.io.IOException;
22  import java.util.ArrayList;
23  import java.util.Iterator;
24  import java.util.List;
25  
26  import javax.faces.application.Resource;
27  import javax.faces.component.UIColumn;
28  import javax.faces.component.UIComponent;
29  import javax.faces.context.FacesContext;
30  import javax.faces.context.ResponseWriter;
31  
32  import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFRenderer;
33  import org.apache.myfaces.custom.tree.HtmlTree;
34  import org.apache.myfaces.custom.tree.HtmlTreeColumn;
35  import org.apache.myfaces.custom.tree.HtmlTreeImageCommandLink;
36  import org.apache.myfaces.custom.tree.HtmlTreeNode;
37  import org.apache.myfaces.custom.tree.IconProvider;
38  import org.apache.myfaces.custom.tree.TreeNode;
39  import org.apache.myfaces.renderkit.html.util.AddResource;
40  import org.apache.myfaces.renderkit.html.util.AddResourceFactory;
41  import org.apache.myfaces.shared_tomahawk.renderkit.JSFAttr;
42  import org.apache.myfaces.shared_tomahawk.renderkit.RendererUtils;
43  import org.apache.myfaces.shared_tomahawk.renderkit.html.HTML;
44  import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlRendererUtils;
45  import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlTableRendererBase;
46  import org.apache.myfaces.shared_tomahawk.util.ArrayUtils;
47  import org.apache.myfaces.shared_tomahawk.util.StringUtils;
48  
49  /**
50   * 
51   * @author <a href="mailto:oliver@rossmueller.com">Oliver Rossmueller </a>
52   * @version $Revision: 659874 $ $Date: 2008-05-24 15:59:15 -0500 (sáb, 24 may 2008) $
53   */
54  @JSFRenderer(
55     renderKitId = "HTML_BASIC", 
56     family = "org.apache.myfaces.HtmlTree",
57     type = "org.apache.myfaces.HtmlTree")
58  public class HtmlTreeRenderer extends HtmlTableRendererBase
59  {
60      // Defaut images
61      private static final String DEFAULT_IMAGE_LIBRARY = "oam.custom.tree.images";
62      private static final String DEFAULT_IMAGE_ICON_LINE = "images/line.gif";
63      private static final String DEFAULT_IMAGE_ICON_NOLINE = "images/noline.gif";
64      private static final String DEFAULT_IMAGE_ICON_CHILD_FIRST = "images/line_first.gif";
65      private static final String DEFAULT_IMAGE_ICON_CHILD_MIDDLE = "images/line_middle.gif";
66      private static final String DEFAULT_IMAGE_ICON_CHILD_LAST = "images/line_last.gif";
67      private static final String DEFAULT_IMAGE_ICON_NODE_OPEN = "images/node_open.gif";
68      private static final String DEFAULT_IMAGE_ICON_NODE_OPEN_FIRST = "images/node_open_first.gif";
69      private static final String DEFAULT_IMAGE_ICON_NODE_OPEN_MIDDLE = "images/node_open_middle.gif";
70      private static final String DEFAULT_IMAGE_ICON_NODE_OPEN_LAST = "images/node_open_last.gif";
71      private static final String DEFAULT_IMAGE_ICON_NODE_CLOSE = "images/node_close.gif";
72      private static final String DEFAULT_IMAGE_ICON_NODE_CLOSE_FIRST = "images/node_close_first.gif";
73      private static final String DEFAULT_IMAGE_ICON_NODE_CLOSE_MIDDLE = "images/node_close_middle.gif";
74      private static final String DEFAULT_IMAGE_ICON_NODE_CLOSE_LAST = "images/node_close_last.gif";
75      
76      private static final String DEFAULT_RESOURCE_ICON_LINE = "line.gif";
77      private static final String DEFAULT_RESOURCE_ICON_NOLINE = "noline.gif";
78      private static final String DEFAULT_RESOURCE_ICON_CHILD_FIRST = "line_first.gif";
79      private static final String DEFAULT_RESOURCE_ICON_CHILD_MIDDLE = "line_middle.gif";
80      private static final String DEFAULT_RESOURCE_ICON_CHILD_LAST = "line_last.gif";
81      private static final String DEFAULT_RESOURCE_ICON_NODE_OPEN = "node_open.gif";
82      private static final String DEFAULT_RESOURCE_ICON_NODE_OPEN_FIRST = "node_open_first.gif";
83      private static final String DEFAULT_RESOURCE_ICON_NODE_OPEN_MIDDLE = "node_open_middle.gif";
84      private static final String DEFAULT_RESOURCE_ICON_NODE_OPEN_LAST = "node_open_last.gif";
85      private static final String DEFAULT_RESOURCE_ICON_NODE_CLOSE = "node_close.gif";
86      private static final String DEFAULT_RESOURCE_ICON_NODE_CLOSE_FIRST = "node_close_first.gif";
87      private static final String DEFAULT_RESOURCE_ICON_NODE_CLOSE_MIDDLE = "node_close_middle.gif";
88      private static final String DEFAULT_RESOURCE_ICON_NODE_CLOSE_LAST = "node_close_last.gif";
89  
90      private static final Integer ZERO = new Integer(0);
91  
92      private static final String DEFAULT_IMAGE_ICON_FOLDER = "images/folder.gif";
93      private static final String DEFAULT_RESOURCE_ICON_FOLDER = "folder.gif";
94  
95      public boolean getRendersChildren()
96      {
97          return true;
98      }
99  
100     public void encodeBegin(FacesContext facesContext, UIComponent uiComponent) throws IOException
101     {
102         // Rendering occurs in encodeEnd.
103     }
104 
105     public void encodeChildren(FacesContext facesContext, UIComponent component) throws IOException
106     {
107         // children are rendered in encodeEnd
108     }
109 
110     public void encodeEnd(FacesContext facesContext, UIComponent component) throws IOException
111     {
112         RendererUtils.checkParamValidity(facesContext, component, HtmlTree.class);
113         ResponseWriter writer = facesContext.getResponseWriter();
114         HtmlTree tree = (HtmlTree) component;
115 
116         HtmlRendererUtils.writePrettyLineSeparator(facesContext);
117         writer.startElement(HTML.TABLE_ELEM, component);
118         HtmlRendererUtils.renderHTMLAttributes(writer, tree, HTML.TABLE_PASSTHROUGH_ATTRIBUTES);
119         writer.writeAttribute(HTML.BORDER_ATTR, ZERO, null);
120         writer.writeAttribute(HTML.CELLSPACING_ATTR, ZERO, null);
121         writer.writeAttribute(HTML.CELLPADDING_ATTR, ZERO, null);
122 
123         int maxLevel = tree.getRootNode().getMaxChildLevel();
124 
125         // Create initial children list from root node facet
126         ArrayList childNodes = new ArrayList(1);
127         childNodes.add(tree.getRootNode());
128 
129         // Render header.
130         renderFacet(facesContext, writer, component, true, maxLevel);
131 
132         // Render children.
133         renderChildren(facesContext, writer, tree, childNodes, maxLevel, tree.getIconProvider(), component);
134 
135         // Render footer.
136         renderFacet(facesContext, writer, component, false, maxLevel);
137         writer.endElement(HTML.TABLE_ELEM);
138     }
139 
140     /**
141      * <p>
142      * Overrides super renderFacet to render the {@link HtmlTree} facets.
143      * <p>
144      *
145      * @param facesContext The facesContext
146      * @param writer The writer.
147      * @param component The component.
148      * @param header Whether there is a header.
149      * @param maxLevel The max level for the rendered tree.
150      * @throws IOException Throws IOException.
151      */
152     protected void renderFacet(FacesContext facesContext, ResponseWriter writer, UIComponent component, boolean header, int maxLevel)
153             throws IOException
154     {
155         int colspan = 0;
156         boolean hasColumnFacet = false;
157         for (Iterator it = component.getChildren().iterator(); it.hasNext();)
158         {
159             UIComponent uiComponent = (UIComponent) it.next();
160             if ((uiComponent.getFamily().equals(UIColumn.COMPONENT_FAMILY))
161                     && ((UIColumn) uiComponent).isRendered())
162             {
163                 colspan++;
164                 if (!hasColumnFacet)
165                 {
166                     hasColumnFacet = header ? ((UIColumn) uiComponent).getHeader() != null : ((UIColumn) uiComponent)
167                             .getFooter() != null;
168                 }
169             }
170             else if ((uiComponent.getFamily().equals(HtmlTreeColumn.COMPONENT_FAMILY))
171                     && ((HtmlTreeColumn) uiComponent).isRendered())
172             {
173                 colspan += maxLevel + 3;
174                 if (!hasColumnFacet)
175                 {
176                     hasColumnFacet = header ? ((UIColumn) uiComponent).getHeader() != null : ((UIColumn) uiComponent)
177                             .getFooter() != null;
178                 }
179             }
180         }
181 
182         UIComponent facet = header ? (UIComponent) component.getFacets().get(HEADER_FACET_NAME)
183                 : (UIComponent) component.getFacets().get(FOOTER_FACET_NAME);
184         if (facet != null || hasColumnFacet)
185         {
186             // Header or Footer present
187             String elemName = header ? HTML.THEAD_ELEM : HTML.TFOOT_ELEM;
188 
189             HtmlRendererUtils.writePrettyLineSeparator(facesContext);
190             writer.startElement(elemName, component);
191             if (header)
192             {
193                 String headerStyleClass = getHeaderClass(component);
194                 if (facet != null)
195                     renderTableHeaderRow(facesContext, writer, component, facet, headerStyleClass, colspan);
196                 if (hasColumnFacet)
197                     renderColumnHeaderRow(facesContext, writer, component, headerStyleClass, maxLevel);
198             }
199             else
200             {
201                 String footerStyleClass = getFooterClass(component);
202                 if (hasColumnFacet)
203                     renderColumnFooterRow(facesContext, writer, component, footerStyleClass, maxLevel);
204                 if (facet != null)
205                     renderTableFooterRow(facesContext, writer, component, facet, footerStyleClass, colspan);
206             }
207             writer.endElement(elemName);
208         }
209     }
210 
211     protected void renderColumnHeaderRow(FacesContext facesContext, ResponseWriter writer, UIComponent component,
212             String headerStyleClass, int maxLevel) throws IOException
213     {
214         renderColumnHeaderOrFooterRow(facesContext, writer, component, headerStyleClass, true, maxLevel);
215     }
216 
217     protected void renderColumnFooterRow(FacesContext facesContext, ResponseWriter writer, UIComponent component,
218             String footerStyleClass, int maxLevel) throws IOException
219     {
220         renderColumnHeaderOrFooterRow(facesContext, writer, component, footerStyleClass, false, maxLevel);
221     }
222 
223     private void renderColumnHeaderOrFooterRow(FacesContext facesContext, ResponseWriter writer, UIComponent component,
224             String styleClass, boolean header, int maxLevel) throws IOException
225     {
226         HtmlRendererUtils.writePrettyLineSeparator(facesContext);
227         writer.startElement(HTML.TR_ELEM, component);
228         for (Iterator it = component.getChildren().iterator(); it.hasNext();)
229         {
230             UIComponent uiComponent = (UIComponent) it.next();
231             if ((uiComponent.getFamily().equals(UIColumn.COMPONENT_FAMILY))
232                     && ((UIColumn) uiComponent).isRendered())
233             {
234                 if (header)
235                 {
236                     renderColumnHeaderCell(facesContext, writer, (UIColumn) uiComponent, styleClass, 0);
237                 }
238                 else
239                 {
240                     renderColumnFooterCell(facesContext, writer, (UIColumn) uiComponent, styleClass, 0);
241                 }
242             }
243             else if ((uiComponent.getFamily().equals(HtmlTreeColumn.COMPONENT_FAMILY))
244                     && ((HtmlTreeColumn) uiComponent).isRendered())
245             {
246                 if (header)
247                 {
248                     renderColumnHeaderCell(facesContext, writer, (UIColumn) uiComponent, styleClass, maxLevel + 3);
249                 }
250                 else
251                 {
252                     renderColumnFooterCell(facesContext, writer, (UIColumn) uiComponent, styleClass, maxLevel + 3);
253                 }
254             }
255         }
256         writer.endElement(HTML.TR_ELEM);
257     }
258 
259     /**
260      * <p>
261      * Renders the children.
262      * </p>
263      *
264      * @param facesContext The facesContext.
265      * @param writer The writer.
266      * @param tree The tree component.
267      * @param children The children to render.
268      * @param maxLevel The maximum level.
269      * @param iconProvider The icon provider.
270      * @throws IOException Throws an IOException.
271      */
272     protected void renderChildren(FacesContext facesContext, ResponseWriter writer, HtmlTree tree, List children,
273             int maxLevel, IconProvider iconProvider, UIComponent component) throws IOException
274     {
275         renderChildren(facesContext, writer, tree, children, maxLevel, iconProvider, 0, component);
276     }
277 
278     /**
279      * <p>
280      * Renders the children given the rowClassIndex.
281      * </p>
282      *
283      * @param facesContext The facesContext.
284      * @param writer The writer.
285      * @param tree The tree component.
286      * @param children The children to render.
287      * @param maxLevel The maximum level.
288      * @param iconProvider The icon provider.
289      * @param rowClassIndex The row class index.
290      * @throws IOException Throws an IOException.
291      */
292     protected void renderChildren(FacesContext facesContext, ResponseWriter writer, HtmlTree tree, List children,
293             int maxLevel, IconProvider iconProvider, int rowClassIndex, UIComponent component) throws IOException
294     {
295         String rowClasses = tree.getRowClasses();
296         String columnClasses = tree.getColumnClasses();
297 
298         String[] rowClassesArray = (rowClasses == null) ? ArrayUtils.EMPTY_STRING_ARRAY : StringUtils.trim(StringUtils
299                 .splitShortString(rowClasses, ','));
300         int rowClassesCount = rowClassesArray.length;
301 
302         String[] columnClassesArray = (columnClasses == null) ? ArrayUtils.EMPTY_STRING_ARRAY : StringUtils
303                 .trim(StringUtils.splitShortString(columnClasses, ','));
304         int columnClassesCount = columnClassesArray.length;
305         int columnClassIndex = 0;
306 
307         for (Iterator it = children.iterator(); it.hasNext();)
308         {
309             HtmlTreeNode child = (HtmlTreeNode) it.next();
310 
311             if (!child.isRendered())
312             {
313                 continue;
314             }
315             HtmlRendererUtils.writePrettyLineSeparator(facesContext);
316 
317             writer.startElement(HTML.TR_ELEM, component);
318 
319             if (rowClassIndex < rowClassesCount)
320             {
321                 writer.writeAttribute(HTML.CLASS_ATTR, rowClassesArray[rowClassIndex], null);
322             }
323             if (rowClassesCount > 0)
324             {
325                 rowClassIndex++;
326                 rowClassIndex = rowClassIndex % rowClassesCount;
327             }
328 
329             if (null != tree.getVar())
330             {
331                 facesContext.getExternalContext().getSessionMap().put(tree.getVar(),
332                         ((TreeNode) child.getUserObject()).getUserObject());
333             }
334 
335             List componentChildren = tree.getChildren();
336             if ((null != componentChildren) && (componentChildren.size() > 0))
337             {
338                 for (int j = 0, size = tree.getChildCount(); j < size; j++)
339                 {
340                     UIComponent componentChild = (UIComponent) componentChildren.get(j);
341                     if ((componentChild.getFamily().equals(UIColumn.COMPONENT_FAMILY))
342                             && ((UIColumn) componentChild).isRendered())
343                     {
344                         writer.startElement(HTML.TD_ELEM, tree);
345                         if (columnClassIndex < columnClassesCount)
346                         {
347                             writer.writeAttribute(HTML.CLASS_ATTR, columnClassesArray[columnClassIndex], null);
348                         }
349                         if (columnClassesCount > 0)
350                         {
351                             columnClassIndex++;
352                             columnClassIndex = columnClassIndex % columnClassesCount;
353                         }
354                         RendererUtils.renderChild(facesContext, componentChild);
355                         writer.endElement(HTML.TD_ELEM);
356                     }
357                     else if ((componentChild.getFamily().equals(HtmlTreeColumn.COMPONENT_FAMILY))
358                             && ((HtmlTreeColumn) componentChild).isRendered())
359                     {
360                         renderTreeColumnChild(facesContext, writer, componentChild, tree, child, maxLevel, iconProvider);
361                     }
362                 }
363             }
364             else
365             {
366                 renderTreeColumnChild(facesContext, writer, null, tree, child, maxLevel, iconProvider);
367             }
368 
369             writer.endElement(HTML.TR_ELEM);
370 
371             if (child.getChildCount() > 0)
372             {
373                 renderChildren(facesContext, writer, tree, child.getChildren(), maxLevel, iconProvider, rowClassIndex, component);
374                 if (rowClassesCount > 0)
375                 {
376                     rowClassIndex += (child.getChildCount() % rowClassesCount);
377                     rowClassIndex = rowClassIndex % rowClassesCount;
378                 }
379             }
380         }
381     }
382 
383     //public String getDefaultImagePath(FacesContext context, String relativePathInResourceFolder)
384     //{
385     //    AddResource instance = AddResourceFactory.getInstance(context);
386     //    return instance.getResourceUri(context, HtmlTree.class, relativePathInResourceFolder, false);
387     //}
388 
389     /**
390      * <p>
391      * Render the column where the tree is displayed.
392      * </p>
393      *
394      * @param facesContext The facesContext.
395      * @param writer The writer.
396      * @param component The component that will contain the tree. Null for
397      *            default tree or {@link HtmlTreeColumn}for table rendering.
398      * @param tree The tree,
399      * @param child The tree node child.
400      * @param maxLevel The max number of levels.
401      * @param iconProvider The iconProvider.
402      * @throws IOException Throws IOException.
403      */
404     protected void renderTreeColumnChild(FacesContext facesContext, ResponseWriter writer, UIComponent component,
405             HtmlTree tree, HtmlTreeNode child, int maxLevel, IconProvider iconProvider) throws IOException
406     {
407         String iconClass = tree.getIconClass();
408         int[] layout = child.getLayout();
409         // tree lines
410         for (int i = 0; i < layout.length - 1; i++)
411         {
412             int state = layout[i];
413             writer.startElement(HTML.TD_ELEM, child);
414             String url = getLayoutImage(facesContext, tree, state);
415 
416             if ((url != null) && (url.length() > 0))
417             {
418                 //writer.startElement(HTML.IMG_ELEM, child);
419 
420                 //String src;
421                 //if (url.startsWith(HTML.HREF_PATH_SEPARATOR))
422                 //{
423                 //    String path = facesContext.getExternalContext().getRequestContextPath();
424                 //    src = path + url;
425                 //}
426                 //else
427                 //{
428                 //    src = url;
429                 //}
430                 //Encode URL
431                 //Although this is an url url, encodeURL is no nonsense,
432                 // because the
433                 //actual url url could also be a dynamic servlet request:
434                 //src = facesContext.getExternalContext().encodeResourceURL(src);
435                 //writer.writeAttribute(HTML.SRC_ATTR, src, null);
436                 //writer.writeAttribute(HTML.BORDER_ATTR, ZERO, null);
437 
438                 //HtmlRendererUtils.renderHTMLAttributes(writer, child, HTML.IMG_PASSTHROUGH_ATTRIBUTES);
439 
440                 //writer.endElement(HTML.IMG_ELEM);
441                 writeImageElement(url, facesContext, writer, child);
442             }
443             else
444             {
445                 String resourceName = getDefaultLayoutResourceName(facesContext, tree, state);
446                 Resource resource = facesContext.getApplication().getResourceHandler().createResource(resourceName, DEFAULT_IMAGE_LIBRARY);
447                 writeImageElementWithoutEncodeResourceURL(resource.getRequestPath(), facesContext, writer, child);
448             }
449             writer.endElement(HTML.TD_ELEM);
450 
451         }
452 
453         // command link
454         writer.startElement(HTML.TD_ELEM, tree);
455         int state = layout[layout.length - 1];
456         String url = getLayoutImage(facesContext, tree, state);
457 
458         if (state == HtmlTreeNode.CHILD || state == HtmlTreeNode.CHILD_FIRST || state == HtmlTreeNode.CHILD_LAST)
459         {
460             // no action, just img
461             if ((url != null) && (url.length() > 0))
462             {
463                 writeImageElement(url, facesContext, writer, child);
464             }
465             else
466             {
467                 String resourceName = getDefaultLayoutResourceName(facesContext, tree, state);
468                 Resource resource = facesContext.getApplication().getResourceHandler().createResource(resourceName, DEFAULT_IMAGE_LIBRARY);
469                 writeImageElementWithoutEncodeResourceURL(resource.getRequestPath(), facesContext, writer, child);
470             }
471         }
472         else
473         {
474             HtmlTreeImageCommandLink expandCollapse = (HtmlTreeImageCommandLink) child
475                     .getExpandCollapseCommand(facesContext);
476             
477             String url1 = getLayoutImage(facesContext, tree, layout[layout.length - 1]);
478             
479             if ((url1 != null) && (url1.length() > 0))
480             {
481                 expandCollapse.setImage(url1);
482             }
483             else
484             {
485                 String resourceName = getDefaultLayoutResourceName(facesContext, tree, layout[layout.length - 1]);
486                 expandCollapse.getAttributes().put(JSFAttr.LIBRARY_ATTR, DEFAULT_IMAGE_LIBRARY);
487                 expandCollapse.getAttributes().put(JSFAttr.NAME_ATTR, resourceName);
488             }
489 
490             expandCollapse.encodeBegin(facesContext);
491             expandCollapse.encodeEnd(facesContext);
492         }
493         writer.endElement(HTML.TD_ELEM);
494 
495         int labelColSpan = maxLevel - child.getLevel() + 1;
496 
497         // node icon
498         if (iconProvider != null)
499         {
500             url = iconProvider.getIconUrl(child.getUserObject(), child.getChildCount(), child.isLeaf(facesContext));
501         }
502         else
503         {
504             //if (!child.isLeaf(facesContext))
505             //{
506                 // todo: icon provider
507                 //url = getDefaultImagePath(facesContext, DEFAULT_IMAGE_ICON_FOLDER );
508             //}
509             //else
510             //{
511                 url = null;
512             //}
513         }
514 
515         if ((url != null) && (url.length() > 0))
516         {
517             writer.startElement(HTML.TD_ELEM, tree);
518             if (iconClass != null)
519             {
520                 writer.writeAttribute(HTML.CLASS_ATTR, iconClass, null);
521             }
522             writeImageElement(url, facesContext, writer, child);
523             writer.endElement(HTML.TD_ELEM);
524         }
525         else if (!child.isLeaf(facesContext) && iconProvider == null)
526         {
527             Resource resource = facesContext.getApplication().getResourceHandler().createResource(DEFAULT_RESOURCE_ICON_FOLDER, DEFAULT_IMAGE_LIBRARY);
528             writer.startElement(HTML.TD_ELEM, tree);
529             if (iconClass != null)
530             {
531                 writer.writeAttribute(HTML.CLASS_ATTR, iconClass, null);
532             }
533             writeImageElementWithoutEncodeResourceURL(resource.getRequestPath(), facesContext, writer, child);
534             writer.endElement(HTML.TD_ELEM);
535         }
536         else
537         {
538             // no icon, so label has more room
539             labelColSpan++;
540         }
541 
542         // node label
543         writer.startElement(HTML.TD_ELEM, tree);
544         writer.writeAttribute(HTML.COLSPAN_ATTR, new Integer(labelColSpan), null);
545         if (child.isSelected() && tree.getSelectedNodeClass() != null)
546         {
547             writer.writeAttribute(HTML.CLASS_ATTR, tree.getSelectedNodeClass(), null);
548         }
549         else if (!child.isSelected() && tree.getNodeClass() != null)
550         {
551             writer.writeAttribute(HTML.CLASS_ATTR, tree.getNodeClass(), null);
552         }
553 
554         List componentChildren = null;
555         if (null != component)
556         {
557             componentChildren = component.getChildren();
558         }
559         if ((null != componentChildren) && (componentChildren.size() > 0))
560         {
561             for (int k = 0; k < componentChildren.size(); k++)
562             {
563                 UIComponent componentChild = (UIComponent) componentChildren.get(k);
564                 RendererUtils.renderChild(facesContext, componentChild);
565             }
566         }
567         else
568         {
569             child.encodeBegin(facesContext);
570             child.encodeEnd(facesContext);
571         }
572         writer.endElement(HTML.TD_ELEM);
573     }
574 
575     private void writeImageElement(String url, FacesContext facesContext, ResponseWriter writer, HtmlTreeNode child)
576             throws IOException
577     {
578         writer.startElement(HTML.IMG_ELEM, child);
579         String src = facesContext.getApplication().getViewHandler().getResourceURL(facesContext, url);
580         //        if (url.startsWith(HTML.HREF_PATH_SEPARATOR))
581         //        {
582         //            String path =
583         // facesContext.getExternalContext().getRequestContextPath();
584         //            src = path + url;
585         //        } else
586         //        {
587         //            src = url;
588         //        }
589         //        //Encode URL
590         //        src = facesContext.getExternalContext().encodeResourceURL(src);
591         writer.writeAttribute(HTML.SRC_ATTR, src, null);
592         writer.writeAttribute(HTML.BORDER_ATTR, ZERO, null);
593 
594         HtmlRendererUtils.renderHTMLAttributes(writer, child, HTML.IMG_PASSTHROUGH_ATTRIBUTES);
595 
596         writer.endElement(HTML.IMG_ELEM);
597     }
598     
599     private void writeImageElementWithoutEncodeResourceURL(String url, FacesContext facesContext, ResponseWriter writer, HtmlTreeNode child)
600         throws IOException
601     {
602         writer.startElement(HTML.IMG_ELEM, child);
603         writer.writeAttribute(HTML.SRC_ATTR, url, null);
604         writer.writeAttribute(HTML.BORDER_ATTR, ZERO, null);
605         HtmlRendererUtils.renderHTMLAttributes(writer, child, HTML.IMG_PASSTHROUGH_ATTRIBUTES);
606         writer.endElement(HTML.IMG_ELEM);
607     }
608 
609     protected String getLayoutImage(FacesContext context, HtmlTree tree, int state)
610     {
611         switch (state)
612         {
613         case HtmlTreeNode.OPEN:
614             return getImageUrl(context, tree.getIconNodeOpenMiddle(), DEFAULT_IMAGE_ICON_NODE_OPEN_MIDDLE);
615         case HtmlTreeNode.OPEN_FIRST:
616             return getImageUrl(context, tree.getIconNodeOpenFirst(), DEFAULT_IMAGE_ICON_NODE_OPEN_FIRST);
617         case HtmlTreeNode.OPEN_LAST:
618             return getImageUrl(context, tree.getIconNodeOpenLast(), DEFAULT_IMAGE_ICON_NODE_OPEN_LAST);            
619         case HtmlTreeNode.OPEN_SINGLE:
620             return getImageUrl(context, tree.getIconNodeOpen(), DEFAULT_IMAGE_ICON_NODE_OPEN);            
621         case HtmlTreeNode.CLOSED:
622             return getImageUrl(context, tree.getIconNodeCloseMiddle(), DEFAULT_IMAGE_ICON_NODE_CLOSE_MIDDLE);            
623         case HtmlTreeNode.CLOSED_FIRST:
624             return getImageUrl(context, tree.getIconNodeCloseFirst(), DEFAULT_IMAGE_ICON_NODE_CLOSE_FIRST);            
625         case HtmlTreeNode.CLOSED_LAST:
626             return getImageUrl(context, tree.getIconNodeCloseLast(), DEFAULT_IMAGE_ICON_NODE_CLOSE_LAST);            
627         case HtmlTreeNode.CLOSED_SINGLE:
628             return getImageUrl(context, tree.getIconNodeClose(), DEFAULT_IMAGE_ICON_NODE_CLOSE);            
629         case HtmlTreeNode.CHILD:
630             return getImageUrl(context, tree.getIconChildMiddle(), DEFAULT_IMAGE_ICON_CHILD_MIDDLE);            
631         case HtmlTreeNode.CHILD_FIRST:
632             return getImageUrl(context, tree.getIconChildFirst(), DEFAULT_IMAGE_ICON_CHILD_FIRST);            
633         case HtmlTreeNode.CHILD_LAST:
634             return getImageUrl(context, tree.getIconChildLast(), DEFAULT_IMAGE_ICON_CHILD_LAST);            
635         case HtmlTreeNode.LINE:
636             return getImageUrl(context, tree.getIconLine(), DEFAULT_IMAGE_ICON_LINE);            
637         case HtmlTreeNode.EMPTY:
638             return getImageUrl(context, tree.getIconNoline(), DEFAULT_IMAGE_ICON_NOLINE);            
639         default:
640             return getImageUrl(context, tree.getIconNoline(), DEFAULT_IMAGE_ICON_NOLINE);
641         }
642     }
643     
644     protected String getDefaultLayoutResourceName(FacesContext context, HtmlTree tree, int state)
645     {
646         switch (state)
647         {
648         case HtmlTreeNode.OPEN:
649             return DEFAULT_RESOURCE_ICON_NODE_OPEN_MIDDLE;
650         case HtmlTreeNode.OPEN_FIRST:
651             return DEFAULT_RESOURCE_ICON_NODE_OPEN_FIRST;
652         case HtmlTreeNode.OPEN_LAST:
653             return DEFAULT_RESOURCE_ICON_NODE_OPEN_LAST;
654         case HtmlTreeNode.OPEN_SINGLE:
655             return DEFAULT_RESOURCE_ICON_NODE_OPEN;
656         case HtmlTreeNode.CLOSED:
657             return DEFAULT_RESOURCE_ICON_NODE_CLOSE_MIDDLE;
658         case HtmlTreeNode.CLOSED_FIRST:
659             return DEFAULT_RESOURCE_ICON_NODE_CLOSE_FIRST;
660         case HtmlTreeNode.CLOSED_LAST:
661             return DEFAULT_RESOURCE_ICON_NODE_CLOSE_LAST;
662         case HtmlTreeNode.CLOSED_SINGLE:
663             return DEFAULT_RESOURCE_ICON_NODE_CLOSE;
664         case HtmlTreeNode.CHILD:
665             return DEFAULT_RESOURCE_ICON_CHILD_MIDDLE;
666         case HtmlTreeNode.CHILD_FIRST:
667             return DEFAULT_RESOURCE_ICON_CHILD_FIRST;
668         case HtmlTreeNode.CHILD_LAST:
669             return DEFAULT_RESOURCE_ICON_CHILD_LAST;
670         case HtmlTreeNode.LINE:
671             return DEFAULT_RESOURCE_ICON_LINE;
672         case HtmlTreeNode.EMPTY:
673             return DEFAULT_RESOURCE_ICON_NOLINE;
674         default:
675             return DEFAULT_RESOURCE_ICON_NOLINE;
676         }
677     }    
678 
679     protected String getImageUrl(FacesContext context, String userValue, String resourceValue)
680     {
681         if(userValue != null)
682         {
683             AddResource addResource = AddResourceFactory.getInstance(context);
684             return addResource.getResourceUri(context, userValue, false);
685         }
686         // Now we use JSF 2.0 Resource api for load default resources, so we need to return null
687         //return addResource.getResourceUri(context, HtmlTree.class, resourceValue, false);
688         return null;
689     }
690 }