FileDocCategorySizeDatePackage
TabbedRenderer.javaAPI DocExample5508Tue Jun 08 11:26:42 BST 2004com.mycompany.jsf.renderer

TabbedRenderer.java

package com.mycompany.jsf.renderer;

import com.mycompany.jsf.component.UITabLabel;

import java.io.IOException;
import java.util.Iterator;
import java.util.List;

import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.component.UIComponent;
import javax.faces.component.UIViewRoot;
import javax.faces.render.Renderer;

/**
 * This class is a JSF Renderer for the "javax.faces.Panel"
 * component type. It renders a table with one row of cells
 * made up from the "label" facets on its children, assumed
 * to be "com.mycompany.TabLabel" components.
 *
 * @author Hans Bergsten, Gefion Software <hans@gefionsoftware.com>
 * @version 1.0
 */
public class TabbedRenderer extends Renderer {

    /**
     * Returns "true".
     */
    public boolean getRendersChildren() {
	return true;
    }

    /**
     * Loops over all children and calls processDecodes() on the
     * child's "label" facet for all children with the "rendered"
     * property set to "false" (the one with "rendered" set to
     * "true" is decoded by the default processing).
     */
    public void decode(FacesContext context, UIComponent component) {
	// "rendered" false are not decoded by default, but the label
	// facets must be
	Iterator i = component.getChildren().iterator();
	while (i.hasNext()) {
	    UIComponent child = (UIComponent) i.next();
	    if (!child.isRendered()) {
		UITabLabel tabLabel = (UITabLabel) child.getFacet("label");
		if (tabLabel != null) {
		    tabLabel.processDecodes(context);
		}
	    }
	}
    }

    /**
     * Ensures that only one child has "rendered" set to "true",
     * renders an HTML table with one row and one cell per child
     * "label" facet, with a "class" attribute for the "table"
     * element set to the "labelAreaClass" component attribute
     * value, and one of "selectedLabelClass" or "unselectedLabelClass"
     * as the "class" attribute value for the "td" elements.
     */
    public void encodeBegin(FacesContext context, UIComponent component)
        throws IOException {

        if (!component.isRendered()) {
            return;
        }

	/*
	 * Figure out which tab is selected (the first one with
	 * "rendered" set to "true"), and ensure all others are
	 * unselected ("rendered" set to "false").
	 */
	int selected = 0;
	List children = component.getChildren();
	boolean pickedSelected = false;
	for (int i = 0; i < children.size(); i++) {
	    UIComponent child = (UIComponent) children.get(i);
	    if (child.isRendered() && !pickedSelected) {
		selected = i;
		pickedSelected = true;
	    }
	    else {
		child.setRendered(false);
	    }
	}

	// Render the tab labels as an HTML table with the appropriate
	// CSS class
        String labelAreaClass =
	    (String) component.getAttributes().get("labelAreaClass");
        String selectedLabelClass =
	    (String) component.getAttributes().get("selectedLabelClass");
        String unselectedLabelClass =
	    (String) component.getAttributes().get("unselectedLabelClass");

        ResponseWriter out = context.getResponseWriter();
	out.startElement("table", component);
	if (component.getId() != null && 
	    !component.getId().startsWith(UIViewRoot.UNIQUE_ID_PREFIX)) {
		out.writeAttribute("id", component.getClientId(context),
		    "id");
	}
	if (labelAreaClass != null) {
	    out.writeAttribute("class", labelAreaClass, "labelAreaClass");
	}

	out.startElement("tr", component);	
	for (int i = 0; i < children.size(); i++) {
	    UIComponent child = (UIComponent) children.get(i);
	    UITabLabel tabLabel = (UITabLabel) child.getFacet("label");
	    if (tabLabel != null) {
		String styleClass = i == selected ? 
		    selectedLabelClass : unselectedLabelClass;
		out.startElement("td", component);
		if (styleClass != null) {
		    out.writeAttribute("class", styleClass, 
			 i == selected ? 
		             "selectedLabelClass" : "unselectedLabelClass");
		}
		encodeRecursive(context, tabLabel);
		out.endElement("td");
	    }
	}
	out.endElement("tr");
	out.endElement("table");
    }

    /**
     * Calls the appropriate encode methods for the child with
     * the "rendered" property set to "true".
     */
    public void encodeChildren(FacesContext context, UIComponent component)
        throws IOException {

	Iterator i = component.getChildren().iterator();
	while (i.hasNext()) {
	    UIComponent child = (UIComponent) i.next();
	    if (child.isRendered()) {
		child.encodeBegin(context);
		if (child.getRendersChildren()) {
		    child.encodeChildren(context);
		}
		child.encodeEnd(context);
	    }
	}
    }

    /**
     * Calls the appropriate encoding methods on the component and
     * calls itself recursively for all component children.
     */
    private void encodeRecursive(FacesContext context, UIComponent component)
        throws IOException {

        if (!component.isRendered()) {
            return;
        }

        component.encodeBegin(context);
        if (component.getRendersChildren()) {
            component.encodeChildren(context);
        } else {
            Iterator i = component.getChildren().iterator();
            while (i.hasNext()) {
                UIComponent child = (UIComponent) i.next();
                encodeRecursive(context, child);
            }
        }
        component.encodeEnd(context);
    }
}