/**
* License Agreement.
*
* JBoss RichFaces - Ajax4jsf Component Library
*
* Copyright (C) 2007 Exadel, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package org.richfaces.renderkit;
import java.io.IOException;
import java.util.Map;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import org.ajax4jsf.component.SequenceDataAdaptor;
import org.ajax4jsf.component.UIDataAdaptor;
import org.ajax4jsf.model.DataVisitor;
import org.ajax4jsf.renderkit.HeaderResourcesRendererBase;
import org.ajax4jsf.renderkit.RendererUtils;
import org.ajax4jsf.renderkit.RendererUtils.HTML;
import org.richfaces.component.Row;
import org.richfaces.component.UIDataTable;
/**
* @author shura
*
*/
public abstract class AbstractRowsRenderer extends HeaderResourcesRendererBase implements
DataVisitor {
public static final String[][] TABLE_EVENT_ATTRS = {
{"onclick","onRowClick"},
{"ondblclick","onRowDblClick"},
{"onmousemove","onRowMouseMove"},
{"onmouseup","onRowMouseUp"},
{"onmousedown","onRowMouseDown"},
{"onmouseover","onRowMouseOver"},
{"onmouseout","onRowMouseOut"}
};
public static final Object ROW_CLASS_KEY = AbstractRowsRenderer.class
.getName()
+ ".rowClass";
public static final Object SKIN_ROW_CLASS_KEY = AbstractRowsRenderer.class
.getName()
+ ".skinRowClass";
public static final Object CELL_CLASS_KEY = AbstractRowsRenderer.class
.getName()
+ ".cellClass";
public static final Object SKIN_CELL_CLASS_KEY = AbstractRowsRenderer.class
.getName()
+ ".skinCellClass";
public static final Object SKIN_FIRST_ROW_CLASS_KEY = AbstractRowsRenderer.class.getName()+".firstRowSkinClass";
/*
* (non-Javadoc)
*
* @see org.ajax4jsf.ajax.repeat.DataVisitor#process(javax.faces.context.FacesContext,
* java.lang.Object, java.lang.Object)
*/
public void process(FacesContext context, Object rowKey, Object argument)
throws IOException {
TableHolder holder = (TableHolder) argument;
UIDataAdaptor table = holder.getTable();
table.setRowKey(context, rowKey);
encodeOneRow(context, holder);
holder.nextRow();
}
public void encodeRows(FacesContext context, UIComponent component) throws IOException {
encodeRows(context, component, new TableHolder((UIDataAdaptor) component));
}
/**
* Iterate over all rows for this table.
*
* @param context
* @param component
* @throws IOException
*/
protected void encodeRows(FacesContext context, UIComponent component, TableHolder tableHolder)
throws IOException {
UIDataAdaptor table = (UIDataAdaptor) component;
Object key = table.getRowKey();
table.captureOrigValue(context);
table.walk(context, this, tableHolder);
doCleanup(context, tableHolder);
table.setRowKey(key);
table.restoreOrigValue(context);
}
/**
* @param context
* TODO
* @param tableHolder
* @throws IOException
*/
protected void doCleanup(FacesContext context, TableHolder tableHolder)
throws IOException {
// Hoock method for perform encoding after all rows is rendered
}
public abstract void encodeOneRow(FacesContext context, TableHolder holder)
throws IOException;
/*
* (non-Javadoc)
*
* @see javax.faces.render.Renderer#getRendersChildren()
*/
public boolean getRendersChildren() {
return true;
}
public void encodeChildren(FacesContext context, UIComponent component)
throws IOException {
encodeRows(context, component);
}
public void encodeCaption(FacesContext context, SequenceDataAdaptor table)
throws IOException {
ResponseWriter writer = context.getResponseWriter();
UIComponent caption = table.getFacet("caption");
if (caption != null) {
String captionClass = (String) table.getAttributes().get(
"captionClass");
String captionStyle = (String) table.getAttributes().get(
"captionStyle");
writer.startElement("caption", table);
if (captionClass != null) {
captionClass = "dr-table-caption rich-table-caption "
+ captionClass;
} else {
captionClass = "dr-table-caption rich-table-caption";
}
writer.writeAttribute("class", captionClass, "captionClass");
if (captionStyle != null) {
writer.writeAttribute("style", captionStyle, "captionStyle");
}
renderChild(context, caption);
writer.endElement("caption");
}
}
/**
* @param context
* @param table
* @throws IOException
*/
protected void encodeRowEvents(FacesContext context, UIDataAdaptor table)
throws IOException {
RendererUtils utils2 = getUtils();
for (int i = 0; i < TABLE_EVENT_ATTRS.length; i++) {
String[] attrs = TABLE_EVENT_ATTRS[i];
utils2.encodeAttribute(context, table, attrs[1], attrs[0]);
}
}
/**
* Encode HTML "class" attribute, if is not empty. Classes combined from
* pre-defined skin classes, class from parent component, and custom
* attribute.
*
* @param writer
* @param parentPredefined TODO
* @param predefined
* predefined skin classes
* @param parent
* class from parent component
* @param custom
* custom classes.
* @throws IOException
*/
protected void encodeStyleClass(ResponseWriter writer, Object parentPredefined,
Object predefined, Object parent, Object custom) throws IOException {
StringBuffer styleClass = new StringBuffer();
// Construct predefined classes
if (null != parentPredefined) {
styleClass.append(parentPredefined).append(" ");
} else if (null != predefined) {
styleClass.append(predefined).append(" ");
}
// Append class from parent component.
if (null != parent) {
styleClass.append(parent).append(" ");
}
if (null != custom) {
styleClass.append(custom);
}
if (styleClass.length() > 0) {
writer.writeAttribute(HTML.class_ATTRIBUTE, styleClass,
"styleClass");
}
}
protected void encodeStyle(ResponseWriter writer, Object parentPredefined,
Object predefined, Object parent, Object custom) throws IOException {
StringBuffer style = new StringBuffer();
// Construct predefined styles
if (null != parentPredefined) {
style.append(parentPredefined).append(" ");
} else if (null != predefined) {
style.append(predefined).append(" ");
}
// Append style from parent component.
if (null != parent) {
style.append(parent).append(" ");
}
if (null != custom) {
style.append(custom);
}
if (style.length() > 0) {
writer.writeAttribute("style", style,
"style");
}
}
/**
* Render component and all its children with current row/cell style
* classes.
*
* @param context
* @param cell
* @param skinFirstRowClass TODO
* @param skinRowClass
* TODO
* @param rowClass
* @param skinCellClass
* TODO
* @param cellClass
* @throws IOException
*/
protected void encodeCellChildren(FacesContext context, UIComponent cell,
String skinFirstRowClass, String skinRowClass, String rowClass,
String skinCellClass, String cellClass) throws IOException {
Map requestMap = context.getExternalContext().getRequestMap();
// Save top level class parameters ( if any ), and put new for this
// component
Object savedRowClass = requestMap.get(ROW_CLASS_KEY);
if (null != rowClass) {
requestMap.put(ROW_CLASS_KEY, rowClass);
}
Object savedSkinFirstRowClass = requestMap.get(SKIN_FIRST_ROW_CLASS_KEY);
if (null != skinRowClass) {
requestMap.put(SKIN_FIRST_ROW_CLASS_KEY, skinFirstRowClass);
}
Object savedSkinRowClass = requestMap.get(SKIN_ROW_CLASS_KEY);
if (null != skinRowClass) {
requestMap.put(SKIN_ROW_CLASS_KEY, skinRowClass);
}
Object savedCellClass = requestMap.get(CELL_CLASS_KEY);
if (null != cellClass) {
requestMap.put(CELL_CLASS_KEY, cellClass);
}
Object savedSkinCellClass = requestMap.get(SKIN_CELL_CLASS_KEY);
if (null != skinCellClass) {
requestMap.put(SKIN_CELL_CLASS_KEY, skinCellClass);
}
renderChild(context, cell);
// Restore original values.
requestMap.put(ROW_CLASS_KEY, savedRowClass);
requestMap.put(CELL_CLASS_KEY, savedCellClass);
requestMap.put(SKIN_FIRST_ROW_CLASS_KEY, savedSkinFirstRowClass);
requestMap.put(SKIN_ROW_CLASS_KEY, savedSkinRowClass);
requestMap.put(SKIN_CELL_CLASS_KEY, savedSkinCellClass);
}
protected void encodeTableHeaderFacet(FacesContext context, int columns, ResponseWriter writer, UIComponent footer, String skinFirstRowClass, String skinRowClass, String skinCellClass, String footerClass, String element) throws IOException {
boolean isColgroup = footer instanceof Row;
if (!isColgroup) {
writer.startElement("tr", footer);
encodeStyleClass(writer, null, skinFirstRowClass, footerClass, null);
writer.startElement(element, footer);
encodeStyleClass(writer, null, skinCellClass, footerClass, null);
if (columns>0) {
writer.writeAttribute("colspan", String.valueOf(columns), null);
}
writer.writeAttribute("scope", "colgroup", null);
}
encodeCellChildren(context, footer,skinFirstRowClass,skinRowClass, footerClass, skinCellClass, null);
if (!isColgroup) {
writer.endElement(element);
writer.endElement("tr");
}
}
}