KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > myfaces > custom > tree > renderkit > html > HtmlTreeRenderer


1 /*
2  * Copyright 2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.myfaces.custom.tree.renderkit.html;
17
18 import org.apache.myfaces.custom.tree.HtmlTree;
19 import org.apache.myfaces.custom.tree.HtmlTreeColumn;
20 import org.apache.myfaces.custom.tree.HtmlTreeImageCommandLink;
21 import org.apache.myfaces.custom.tree.HtmlTreeNode;
22 import org.apache.myfaces.custom.tree.IconProvider;
23 import org.apache.myfaces.custom.tree.TreeNode;
24 import org.apache.myfaces.renderkit.RendererUtils;
25 import org.apache.myfaces.renderkit.html.HTML;
26 import org.apache.myfaces.renderkit.html.HtmlRendererUtils;
27 import org.apache.myfaces.renderkit.html.HtmlTableRendererBase;
28 import org.apache.myfaces.util.ArrayUtils;
29 import org.apache.myfaces.util.StringUtils;
30
31 import javax.faces.component.UIColumn;
32 import javax.faces.component.UIComponent;
33 import javax.faces.context.FacesContext;
34 import javax.faces.context.ResponseWriter;
35
36 import java.io.IOException JavaDoc;
37 import java.util.ArrayList JavaDoc;
38 import java.util.Iterator JavaDoc;
39 import java.util.List JavaDoc;
40
41 /**
42  * @author <a HREF="mailto:oliver@rossmueller.com">Oliver Rossmueller </a>
43  * @version $Revision: 1.16 $ $Date: 2005/02/11 00:54:02 $
44  *
45  * $Log: HtmlTreeRenderer.java,v $
46  * Revision 1.16 2005/02/11 00:54:02 svieujot
47  * Revert changes commited to the wrong branch.
48  *
49  * Revision 1.14 2004/12/24 14:13:16 svieujot
50  * Upgrade the tree component to use the Extensions filter.
51  *
52  * Revision 1.13 2004/12/22 17:52:54 grantsmith
53  * Jira MYFACES-48: Tree Table Component Fixes & Tree Checkbox Support
54  *
55  * Revision 1.12 2004/11/26 12:46:38 oros
56  * cleanup: removed unused iconChild attribute
57  *
58  * Revision 1.11 2004/11/26 12:14:09 oros
59  * MYFACES-8: applied tree table patch by David Le Strat
60  *
61  *
62  */

63 public class HtmlTreeRenderer extends HtmlTableRendererBase
64 {
65
66     private static final Integer JavaDoc ZERO = new Integer JavaDoc(0);
67     
68     private static final String JavaDoc DEFAULT_IMAGE_ICON_FOLDER = "images/folder.gif";
69
70     public boolean getRendersChildren()
71     {
72         return true;
73     }
74
75     public void encodeBegin(FacesContext facesContext, UIComponent uiComponent) throws IOException JavaDoc
76     {
77         // Rendering occurs in encodeEnd.
78
}
79
80     public void encodeChildren(FacesContext facesContext, UIComponent component) throws IOException JavaDoc
81     {
82         // children are rendered in encodeEnd
83
}
84
85     public void encodeEnd(FacesContext facesContext, UIComponent component) throws IOException JavaDoc
86     {
87         RendererUtils.checkParamValidity(facesContext, component, HtmlTree.class);
88         ResponseWriter writer = facesContext.getResponseWriter();
89         HtmlTree tree = (HtmlTree) component;
90
91         HtmlRendererUtils.writePrettyLineSeparator(facesContext);
92         writer.startElement(HTML.TABLE_ELEM, null);
93         HtmlRendererUtils.renderHTMLAttributes(writer, tree, HTML.TABLE_PASSTHROUGH_ATTRIBUTES);
94         writer.writeAttribute(HTML.BORDER_ATTR, ZERO, null);
95         writer.writeAttribute(HTML.CELLSPACING_ATTR, ZERO, null);
96         writer.writeAttribute(HTML.CELLPADDING_ATTR, ZERO, null);
97
98         int maxLevel = tree.getRootNode().getMaxChildLevel();
99
100         // Create initial children list from root node facet
101
ArrayList JavaDoc childNodes = new ArrayList JavaDoc(1);
102         childNodes.add(tree.getRootNode());
103
104         // Render header.
105
renderFacet(facesContext, writer, component, true, maxLevel);
106
107         // Render children.
108
renderChildren(facesContext, writer, tree, childNodes, maxLevel, tree.getIconProvider());
109
110         // Render footer.
111
renderFacet(facesContext, writer, component, false, maxLevel);
112         writer.endElement(HTML.TABLE_ELEM);
113     }
114
115     /**
116      * <p>
117      * Overrides super renderFacet to render the {@link HtmlTree} facets.
118      * <p>
119      *
120      * @param facesContext The facesContext
121      * @param writer The writer.
122      * @param component The component.
123      * @param header Whether there is a header.
124      * @param maxLevel The max level for the rendered tree.
125      * @throws IOException Throws IOException.
126      */

127     protected void renderFacet(FacesContext facesContext, ResponseWriter writer, UIComponent component, boolean header, int maxLevel)
128             throws IOException JavaDoc
129     {
130         int colspan = 0;
131         boolean hasColumnFacet = false;
132         for (Iterator JavaDoc it = component.getChildren().iterator(); it.hasNext();)
133         {
134             UIComponent uiComponent = (UIComponent) it.next();
135             if ((uiComponent.getFamily().equals(UIColumn.COMPONENT_FAMILY))
136                     && ((UIColumn) uiComponent).isRendered())
137             {
138                 colspan++;
139                 if (!hasColumnFacet)
140                 {
141                     hasColumnFacet = header ? ((UIColumn) uiComponent).getHeader() != null : ((UIColumn) uiComponent)
142                             .getFooter() != null;
143                 }
144             }
145             else if ((uiComponent.getFamily().equals(HtmlTreeColumn.COMPONENT_FAMILY))
146                     && ((HtmlTreeColumn) uiComponent).isRendered())
147             {
148                 colspan += maxLevel + 3;
149                 if (!hasColumnFacet)
150                 {
151                     hasColumnFacet = header ? ((UIColumn) uiComponent).getHeader() != null : ((UIColumn) uiComponent)
152                             .getFooter() != null;
153                 }
154             }
155         }
156
157         UIComponent facet = header ? (UIComponent) component.getFacets().get(HEADER_FACET_NAME)
158                 : (UIComponent) component.getFacets().get(FOOTER_FACET_NAME);
159         if (facet != null || hasColumnFacet)
160         {
161             // Header or Footer present
162
String JavaDoc elemName = header ? HTML.THEAD_ELEM : HTML.TFOOT_ELEM;
163
164             HtmlRendererUtils.writePrettyLineSeparator(facesContext);
165             writer.startElement(elemName, component);
166             if (header)
167             {
168                 String JavaDoc headerStyleClass = getHeaderClass(component);
169                 if (facet != null)
170                     renderTableHeaderRow(facesContext, writer, component, facet, headerStyleClass, colspan);
171                 if (hasColumnFacet)
172                     renderColumnHeaderRow(facesContext, writer, component, headerStyleClass, maxLevel);
173             }
174             else
175             {
176                 String JavaDoc footerStyleClass = getFooterClass(component);
177                 if (hasColumnFacet)
178                     renderColumnFooterRow(facesContext, writer, component, footerStyleClass, maxLevel);
179                 if (facet != null)
180                     renderTableFooterRow(facesContext, writer, component, facet, footerStyleClass, colspan);
181             }
182             writer.endElement(elemName);
183         }
184     }
185
186     protected void renderColumnHeaderRow(FacesContext facesContext, ResponseWriter writer, UIComponent component,
187             String JavaDoc headerStyleClass, int maxLevel) throws IOException JavaDoc
188     {
189         renderColumnHeaderOrFooterRow(facesContext, writer, component, headerStyleClass, true, maxLevel);
190     }
191
192     protected void renderColumnFooterRow(FacesContext facesContext, ResponseWriter writer, UIComponent component,
193             String JavaDoc footerStyleClass, int maxLevel) throws IOException JavaDoc
194     {
195         renderColumnHeaderOrFooterRow(facesContext, writer, component, footerStyleClass, false, maxLevel);
196     }
197
198     private void renderColumnHeaderOrFooterRow(FacesContext facesContext, ResponseWriter writer, UIComponent component,
199             String JavaDoc styleClass, boolean header, int maxLevel) throws IOException JavaDoc
200     {
201         HtmlRendererUtils.writePrettyLineSeparator(facesContext);
202         writer.startElement(HTML.TR_ELEM, component);
203         for (Iterator JavaDoc it = component.getChildren().iterator(); it.hasNext();)
204         {
205             UIComponent uiComponent = (UIComponent) it.next();
206             if ((uiComponent.getFamily().equals(UIColumn.COMPONENT_FAMILY))
207                     && ((UIColumn) uiComponent).isRendered())
208             {
209                 if (header)
210                 {
211                     renderColumnHeaderCell(facesContext, writer, (UIColumn) uiComponent, styleClass, 0);
212                 }
213                 else
214                 {
215                     renderColumnFooterCell(facesContext, writer, (UIColumn) uiComponent, styleClass, 0);
216                 }
217             }
218             else if ((uiComponent.getFamily().equals(HtmlTreeColumn.COMPONENT_FAMILY))
219                     && ((HtmlTreeColumn) uiComponent).isRendered())
220             {
221                 if (header)
222                 {
223                     renderColumnHeaderCell(facesContext, writer, (UIColumn) uiComponent, styleClass, maxLevel + 3);
224                 }
225                 else
226                 {
227                     renderColumnFooterCell(facesContext, writer, (UIColumn) uiComponent, styleClass, maxLevel + 3);
228                 }
229             }
230         }
231         writer.endElement(HTML.TR_ELEM);
232     }
233
234     /**
235      * <p>
236      * Renders the children.
237      * </p>
238      *
239      * @param facesContext The facesContext.
240      * @param writer The writer.
241      * @param tree The tree component.
242      * @param children The children to render.
243      * @param maxLevel The maximum level.
244      * @param iconProvider The icon provider.
245      * @throws IOException Throws an IOException.
246      */

247     protected void renderChildren(FacesContext facesContext, ResponseWriter writer, HtmlTree tree, List JavaDoc children,
248             int maxLevel, IconProvider iconProvider) throws IOException JavaDoc
249     {
250         renderChildren(facesContext, writer, tree, children, maxLevel, iconProvider, 0);
251     }
252
253     /**
254      * <p>
255      * Renders the children given the rowClassIndex.
256      * </p>
257      *
258      * @param facesContext The facesContext.
259      * @param writer The writer.
260      * @param tree The tree component.
261      * @param children The children to render.
262      * @param maxLevel The maximum level.
263      * @param iconProvider The icon provider.
264      * @param rowClassIndex The row class index.
265      * @throws IOException Throws an IOException.
266      */

267     protected void renderChildren(FacesContext facesContext, ResponseWriter writer, HtmlTree tree, List JavaDoc children,
268             int maxLevel, IconProvider iconProvider, int rowClassIndex) throws IOException JavaDoc
269     {
270         String JavaDoc rowClasses = tree.getRowClasses();
271         String JavaDoc columnClasses = tree.getColumnClasses();
272
273         String JavaDoc[] rowClassesArray = (rowClasses == null) ? ArrayUtils.EMPTY_STRING_ARRAY : StringUtils.trim(StringUtils
274                 .splitShortString(rowClasses, ','));
275         int rowClassesCount = rowClassesArray.length;
276
277         String JavaDoc[] columnClassesArray = (columnClasses == null) ? ArrayUtils.EMPTY_STRING_ARRAY : StringUtils
278                 .trim(StringUtils.splitShortString(columnClasses, ','));
279         int columnClassesCount = columnClassesArray.length;
280         int columnClassIndex = 0;
281
282         for (Iterator JavaDoc it = children.iterator(); it.hasNext();)
283         {
284             HtmlTreeNode child = (HtmlTreeNode) it.next();
285
286             if (!child.isRendered())
287             {
288                 continue;
289             }
290             HtmlRendererUtils.writePrettyLineSeparator(facesContext);
291
292             writer.startElement(HTML.TR_ELEM, null);
293
294             if (rowClassIndex < rowClassesCount)
295             {
296                 writer.writeAttribute(HTML.CLASS_ATTR, rowClassesArray[rowClassIndex], null);
297             }
298             if (rowClassesCount > 0)
299             {
300                 rowClassIndex++;
301                 rowClassIndex = rowClassIndex % rowClassesCount;
302             }
303
304             if (null != tree.getVar())
305             {
306                 facesContext.getExternalContext().getSessionMap().put(tree.getVar(),
307                         ((TreeNode) child.getUserObject()).getUserObject());
308             }
309
310             List JavaDoc componentChildren = tree.getChildren();
311             if ((null != componentChildren) && (componentChildren.size() > 0))
312             {
313                 for (int j = 0, size = tree.getChildCount(); j < size; j++)
314                 {
315                     UIComponent componentChild = (UIComponent) componentChildren.get(j);
316                     if ((componentChild.getFamily().equals(UIColumn.COMPONENT_FAMILY))
317                             && ((UIColumn) componentChild).isRendered())
318                     {
319                         writer.startElement(HTML.TD_ELEM, tree);
320                         if (columnClassIndex < columnClassesCount)
321                         {
322                             writer.writeAttribute(HTML.CLASS_ATTR, columnClassesArray[columnClassIndex], null);
323                         }
324                         if (columnClassesCount > 0)
325                         {
326                             columnClassIndex++;
327                             columnClassIndex = columnClassIndex % columnClassesCount;
328                         }
329                         RendererUtils.renderChild(facesContext, componentChild);
330                         writer.endElement(HTML.TD_ELEM);
331                     }
332                     else if ((componentChild.getFamily().equals(HtmlTreeColumn.COMPONENT_FAMILY))
333                             && ((HtmlTreeColumn) componentChild).isRendered())
334                     {
335                         renderTreeColumnChild(facesContext, writer, componentChild, tree, child, maxLevel, iconProvider);
336                     }
337                 }
338             }
339             else
340             {
341                 renderTreeColumnChild(facesContext, writer, null, tree, child, maxLevel, iconProvider);
342             }
343
344             writer.endElement(HTML.TR_ELEM);
345
346             if (child.getChildCount() > 0)
347             {
348                 renderChildren(facesContext, writer, tree, child.getChildren(), maxLevel, iconProvider, rowClassIndex);
349                 if (rowClassesCount > 0)
350                 {
351                     rowClassIndex += (child.getChildCount() % rowClassesCount);
352                     rowClassIndex = rowClassIndex % rowClassesCount;
353                 }
354             }
355         }
356     }
357
358     /**
359      * <p>
360      * Render the column where the tree is displayed.
361      * </p>
362      *
363      * @param facesContext The facesContext.
364      * @param writer The writer.
365      * @param component The component that will contain the tree. Null for
366      * default tree or {@link HtmlTreeColumn}for table rendering.
367      * @param tree The tree,
368      * @param child The tree node child.
369      * @param maxLevel The max number of levels.
370      * @param iconProvider The iconProvider.
371      * @throws IOException Throws IOException.
372      */

373     protected void renderTreeColumnChild(FacesContext facesContext, ResponseWriter writer, UIComponent component,
374             HtmlTree tree, HtmlTreeNode child, int maxLevel, IconProvider iconProvider) throws IOException JavaDoc
375     {
376         String JavaDoc iconClass = tree.getIconClass();
377         int[] layout = child.getLayout();
378         // tree lines
379
for (int i = 0; i < layout.length - 1; i++)
380         {
381             int state = layout[i];
382             writer.startElement(HTML.TD_ELEM, null);
383             String JavaDoc url = getLayoutImage(tree, state);
384
385             if ((url != null) && (url.length() > 0))
386             {
387                 //writer.startElement(HTML.IMG_ELEM, child);
388

389                 //String src;
390
//if (url.startsWith(HTML.HREF_PATH_SEPARATOR))
391
//{
392
// String path = facesContext.getExternalContext().getRequestContextPath();
393
// src = path + url;
394
//}
395
//else
396
//{
397
// src = url;
398
//}
399
//Encode URL
400
//Although this is an url url, encodeURL is no nonsense,
401
// because the
402
//actual url url could also be a dynamic servlet request:
403
//src = facesContext.getExternalContext().encodeResourceURL(src);
404
//writer.writeAttribute(HTML.SRC_ATTR, src, null);
405
//writer.writeAttribute(HTML.BORDER_ATTR, ZERO, null);
406

407                 //HtmlRendererUtils.renderHTMLAttributes(writer, child, HTML.IMG_PASSTHROUGH_ATTRIBUTES);
408

409                 //writer.endElement(HTML.IMG_ELEM);
410
writeImageElement(url, facesContext, writer, child);
411             }
412             writer.endElement(HTML.TD_ELEM);
413
414         }
415
416         // command link
417
writer.startElement(HTML.TD_ELEM, null);
418         int state = layout[layout.length - 1];
419         String JavaDoc url = getLayoutImage(tree, state);
420
421         if (state == HtmlTreeNode.CHILD || state == HtmlTreeNode.CHILD_FIRST || state == HtmlTreeNode.CHILD_LAST)
422         {
423             // no action, just img
424
writeImageElement(url, facesContext, writer, child);
425         }
426         else
427         {
428             HtmlTreeImageCommandLink expandCollapse = (HtmlTreeImageCommandLink) child
429                     .getExpandCollapseCommand(facesContext);
430             expandCollapse.setImage(getLayoutImage(tree, layout[layout.length - 1]));
431
432             expandCollapse.encodeBegin(facesContext);
433             expandCollapse.encodeEnd(facesContext);
434         }
435         writer.endElement(HTML.TD_ELEM);
436
437         int labelColSpan = maxLevel - child.getLevel() + 1;
438
439         // node icon
440
if (iconProvider != null)
441         {
442             url = iconProvider.getIconUrl(child.getUserObject(), child.getChildCount(), child.isLeaf(facesContext));
443         }
444         else
445         {
446             if (!child.isLeaf(facesContext))
447             {
448                 // todo: icon provider
449
url = HtmlTree.getDefaultImagePath( DEFAULT_IMAGE_ICON_FOLDER );
450             }
451             else
452             {
453                 url = null;
454             }
455         }
456
457         if ((url != null) && (url.length() > 0))
458         {
459             writer.startElement(HTML.TD_ELEM, null);
460             if (iconClass != null)
461             {
462                 writer.writeAttribute(HTML.CLASS_ATTR, iconClass, null);
463             }
464             writeImageElement(url, facesContext, writer, child);
465             writer.endElement(HTML.TD_ELEM);
466         }
467         else
468         {
469             // no icon, so label has more room
470
labelColSpan++;
471         }
472
473         // node label
474
writer.startElement(HTML.TD_ELEM, null);
475         writer.writeAttribute(HTML.COLSPAN_ATTR, new Integer JavaDoc(labelColSpan), null);
476         if (child.isSelected() && tree.getSelectedNodeClass() != null)
477         {
478             writer.writeAttribute(HTML.CLASS_ATTR, tree.getSelectedNodeClass(), null);
479         }
480         else if (!child.isSelected() && tree.getNodeClass() != null)
481         {
482             writer.writeAttribute(HTML.CLASS_ATTR, tree.getNodeClass(), null);
483         }
484
485         List JavaDoc componentChildren = null;
486         if (null != component)
487         {
488             componentChildren = component.getChildren();
489         }
490         if ((null != componentChildren) && (componentChildren.size() > 0))
491         {
492             for (int k = 0; k < componentChildren.size(); k++)
493             {
494                 UIComponent componentChild = (UIComponent) componentChildren.get(k);
495                 RendererUtils.renderChild(facesContext, componentChild);
496             }
497         }
498         else
499         {
500             child.encodeBegin(facesContext);
501             child.encodeEnd(facesContext);
502         }
503         writer.endElement(HTML.TD_ELEM);
504     }
505
506     private void writeImageElement(String JavaDoc url, FacesContext facesContext, ResponseWriter writer, HtmlTreeNode child)
507             throws IOException JavaDoc
508     {
509         writer.startElement(HTML.IMG_ELEM, child);
510         String JavaDoc src = facesContext.getApplication().getViewHandler().getResourceURL(facesContext, url);
511         // if (url.startsWith(HTML.HREF_PATH_SEPARATOR))
512
// {
513
// String path =
514
// facesContext.getExternalContext().getRequestContextPath();
515
// src = path + url;
516
// } else
517
// {
518
// src = url;
519
// }
520
// //Encode URL
521
// src = facesContext.getExternalContext().encodeResourceURL(src);
522
writer.writeAttribute(HTML.SRC_ATTR, src, null);
523         writer.writeAttribute(HTML.BORDER_ATTR, ZERO, null);
524
525         HtmlRendererUtils.renderHTMLAttributes(writer, child, HTML.IMG_PASSTHROUGH_ATTRIBUTES);
526
527         writer.endElement(HTML.IMG_ELEM);
528     }
529
530     protected String JavaDoc getLayoutImage(HtmlTree tree, int state)
531     {
532         switch (state)
533         {
534         case HtmlTreeNode.OPEN:
535             return tree.getIconNodeOpenMiddle();
536         case HtmlTreeNode.OPEN_FIRST:
537             return tree.getIconNodeOpenFirst();
538         case HtmlTreeNode.OPEN_LAST:
539             return tree.getIconNodeOpenLast();
540         case HtmlTreeNode.OPEN_SINGLE:
541             return tree.getIconNodeOpen();
542         case HtmlTreeNode.CLOSED:
543             return tree.getIconNodeCloseMiddle();
544         case HtmlTreeNode.CLOSED_FIRST:
545             return tree.getIconNodeCloseFirst();
546         case HtmlTreeNode.CLOSED_LAST:
547             return tree.getIconNodeCloseLast();
548         case HtmlTreeNode.CLOSED_SINGLE:
549             return tree.getIconNodeClose();
550         case HtmlTreeNode.CHILD:
551             return tree.getIconChildMiddle();
552         case HtmlTreeNode.CHILD_FIRST:
553             return tree.getIconChildFirst();
554         case HtmlTreeNode.CHILD_LAST:
555             return tree.getIconChildLast();
556         case HtmlTreeNode.LINE:
557             return tree.getIconLine();
558         case HtmlTreeNode.EMPTY:
559             return tree.getIconNoline();
560         default:
561             return tree.getIconNoline();
562         }
563     }
564 }
Popular Tags