1 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 ; 37 import java.util.ArrayList ; 38 import java.util.Iterator ; 39 import java.util.List ; 40 41 63 public class HtmlTreeRenderer extends HtmlTableRendererBase 64 { 65 66 private static final Integer ZERO = new Integer (0); 67 68 private static final String 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 76 { 77 } 79 80 public void encodeChildren(FacesContext facesContext, UIComponent component) throws IOException 81 { 82 } 84 85 public void encodeEnd(FacesContext facesContext, UIComponent component) throws IOException 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 ArrayList childNodes = new ArrayList (1); 102 childNodes.add(tree.getRootNode()); 103 104 renderFacet(facesContext, writer, component, true, maxLevel); 106 107 renderChildren(facesContext, writer, tree, childNodes, maxLevel, tree.getIconProvider()); 109 110 renderFacet(facesContext, writer, component, false, maxLevel); 112 writer.endElement(HTML.TABLE_ELEM); 113 } 114 115 127 protected void renderFacet(FacesContext facesContext, ResponseWriter writer, UIComponent component, boolean header, int maxLevel) 128 throws IOException 129 { 130 int colspan = 0; 131 boolean hasColumnFacet = false; 132 for (Iterator 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 String elemName = header ? HTML.THEAD_ELEM : HTML.TFOOT_ELEM; 163 164 HtmlRendererUtils.writePrettyLineSeparator(facesContext); 165 writer.startElement(elemName, component); 166 if (header) 167 { 168 String 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 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 headerStyleClass, int maxLevel) throws IOException 188 { 189 renderColumnHeaderOrFooterRow(facesContext, writer, component, headerStyleClass, true, maxLevel); 190 } 191 192 protected void renderColumnFooterRow(FacesContext facesContext, ResponseWriter writer, UIComponent component, 193 String footerStyleClass, int maxLevel) throws IOException 194 { 195 renderColumnHeaderOrFooterRow(facesContext, writer, component, footerStyleClass, false, maxLevel); 196 } 197 198 private void renderColumnHeaderOrFooterRow(FacesContext facesContext, ResponseWriter writer, UIComponent component, 199 String styleClass, boolean header, int maxLevel) throws IOException 200 { 201 HtmlRendererUtils.writePrettyLineSeparator(facesContext); 202 writer.startElement(HTML.TR_ELEM, component); 203 for (Iterator 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 247 protected void renderChildren(FacesContext facesContext, ResponseWriter writer, HtmlTree tree, List children, 248 int maxLevel, IconProvider iconProvider) throws IOException 249 { 250 renderChildren(facesContext, writer, tree, children, maxLevel, iconProvider, 0); 251 } 252 253 267 protected void renderChildren(FacesContext facesContext, ResponseWriter writer, HtmlTree tree, List children, 268 int maxLevel, IconProvider iconProvider, int rowClassIndex) throws IOException 269 { 270 String rowClasses = tree.getRowClasses(); 271 String columnClasses = tree.getColumnClasses(); 272 273 String [] rowClassesArray = (rowClasses == null) ? ArrayUtils.EMPTY_STRING_ARRAY : StringUtils.trim(StringUtils 274 .splitShortString(rowClasses, ',')); 275 int rowClassesCount = rowClassesArray.length; 276 277 String [] 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 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 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 373 protected void renderTreeColumnChild(FacesContext facesContext, ResponseWriter writer, UIComponent component, 374 HtmlTree tree, HtmlTreeNode child, int maxLevel, IconProvider iconProvider) throws IOException 375 { 376 String iconClass = tree.getIconClass(); 377 int[] layout = child.getLayout(); 378 for (int i = 0; i < layout.length - 1; i++) 380 { 381 int state = layout[i]; 382 writer.startElement(HTML.TD_ELEM, null); 383 String url = getLayoutImage(tree, state); 384 385 if ((url != null) && (url.length() > 0)) 386 { 387 389 407 409 writeImageElement(url, facesContext, writer, child); 411 } 412 writer.endElement(HTML.TD_ELEM); 413 414 } 415 416 writer.startElement(HTML.TD_ELEM, null); 418 int state = layout[layout.length - 1]; 419 String url = getLayoutImage(tree, state); 420 421 if (state == HtmlTreeNode.CHILD || state == HtmlTreeNode.CHILD_FIRST || state == HtmlTreeNode.CHILD_LAST) 422 { 423 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 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 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 labelColSpan++; 471 } 472 473 writer.startElement(HTML.TD_ELEM, null); 475 writer.writeAttribute(HTML.COLSPAN_ATTR, new Integer (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 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 url, FacesContext facesContext, ResponseWriter writer, HtmlTreeNode child) 507 throws IOException 508 { 509 writer.startElement(HTML.IMG_ELEM, child); 510 String src = facesContext.getApplication().getViewHandler().getResourceURL(facesContext, url); 511 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 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 |