All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.myfaces.renderkit.html.ext.HtmlTableRenderer Maven / Gradle / Ivy

Go to download

JSF components and utilities that can be used with any JSF implementation. This library is based on the JSF1.1 version of Tomahawk, but with minor source code and build changes to take advantage of JSF1.2 features. A JSF1.2 implementation is required to use this version of the Tomahawk library.

The newest version!
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.apache.myfaces.renderkit.html.ext;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.myfaces.component.NewspaperTable;
import org.apache.myfaces.component.html.ext.HtmlDataTable;
import org.apache.myfaces.custom.column.HtmlColumn;
import org.apache.myfaces.custom.column.HtmlSimpleColumn;
import org.apache.myfaces.custom.crosstable.UIColumns;
import org.apache.myfaces.renderkit.html.util.ColumnInfo;
import org.apache.myfaces.renderkit.html.util.RowInfo;
import org.apache.myfaces.renderkit.html.util.TableContext;
import org.apache.myfaces.shared_tomahawk.renderkit.JSFAttr;
import org.apache.myfaces.shared_tomahawk.renderkit.RendererUtils;
import org.apache.myfaces.shared_tomahawk.renderkit.html.HTML;
import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlRendererUtils;
import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlTableRendererBase;
import org.apache.myfaces.shared_tomahawk.util.ArrayUtils;

import javax.faces.component.UIComponent;
import javax.faces.component.UIData;
import javax.faces.component.ValueHolder;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Renderer for the Tomahawk extended HtmlDataTable component.
 *
 * @JSFRenderer
 *   renderKitId = "HTML_BASIC"
 *   family = "javax.faces.Data"
 *   type = "org.apache.myfaces.Table" 
 *   
 * @author Manfred Geiler (latest modification by $Author: lu4242 $)
 * @version $Revision: 1353439 $ $Date: 2012-06-25 04:12:06 -0500 (Mon, 25 Jun 2012) $
 */
public class HtmlTableRenderer extends HtmlTableRendererBase {
    private static final Log log = LogFactory.getLog(HtmlTableRenderer.class);

    /**
     * DetailStamp facet name.
     */
    public static final String DETAIL_STAMP_FACET_NAME = "detailStamp";
    private static final String BODY_STYLE_CLASS = "bodyStyleClass";
    private static final String BODY_STYLE = "bodyStyle";

    /**
     * @param component dataTable
     * @return number of layout columns
     */
    protected int getNewspaperColumns(UIComponent component) {
        if (component instanceof NewspaperTable) {
            // the number of slices to break the table up into */
            NewspaperTable newspaperTable = (NewspaperTable) component;
            return newspaperTable.getNewspaperColumns();
        }
        return super.getNewspaperColumns(component);
    }

    /**
     * @param component dataTable
     * @return component to display between layout columns
     */
    protected UIComponent getNewspaperTableSpacer(UIComponent component) {
        if (component instanceof NewspaperTable) {
            // the number of slices to break the table up into */
            NewspaperTable newspaperTable = (NewspaperTable) component;
            return newspaperTable.getSpacer();
        }
        return super.getNewspaperTableSpacer(component);
    }

    /**
     * @param component dataTable
     * @return whether dataTable has component to display between layout columns
     */
    protected boolean hasNewspaperTableSpacer(UIComponent component) {
        if (null != getNewspaperTableSpacer(component)) {
            return true;
        }
        return super.hasNewspaperTableSpacer(component);
    }

    /**
     * @param component dataTable
     * @return if the orientation of the has newspaper columns is horizontal
     */
    protected boolean isNewspaperHorizontalOrientation(UIComponent component) {
        if (component instanceof NewspaperTable) {
            // get the value of the newspaperOrientation attribute, any value besides horizontal
            // means vertical, the default
            NewspaperTable newspaperTable = (NewspaperTable) component;
            return NewspaperTable.NEWSPAPER_HORIZONTAL_ORIENTATION.equals(newspaperTable.getNewspaperOrientation());
        }
        return super.isNewspaperHorizontalOrientation(component);
    }

    protected void startTable(FacesContext facesContext, UIComponent uiComponent) throws IOException {
        boolean embedded = isEmbeddedTable(uiComponent);

        if (!embedded) {
            super.startTable(facesContext, uiComponent);
        }
    }

    protected String determineHeaderFooterTag(FacesContext facesContext, UIComponent component, boolean header) {
        if (isEmbeddedTable(component)) {
            // we are embedded, so do not render the tfoot/thead stuff
            return null;
        }

        return super.determineHeaderFooterTag(facesContext, component, header);
    }

    protected String determineHeaderCellTag(FacesContext facesContext, UIComponent component) {
        if (isEmbeddedTable(component)) {
            return HTML.TD_ELEM;
        }

        return HTML.TH_ELEM;
    }

    protected void renderTableHeaderOrFooterRow(FacesContext facesContext, ResponseWriter writer, UIComponent component, UIComponent facet, String styleClass, String colElementName, int colspan, boolean isHeader) throws IOException {
        if (isEmbeddedTable(component)) {
            // embedded tables render the header/footer stuff using TD only
            colElementName = HTML.TD_ELEM;
        }

        super.renderTableHeaderOrFooterRow(facesContext, writer, component, facet, styleClass, colElementName, colspan, isHeader);
    }

    protected boolean isEmbeddedTable(UIComponent uiComponent) {
        boolean embedded = false;
        if (uiComponent instanceof HtmlDataTable) {
            HtmlDataTable table = (HtmlDataTable) uiComponent;
            embedded = table.isEmbedded();
        }
        return embedded;
    }

    protected boolean isDetailStampAfterRow(UIComponent uiComponent) {
        if (uiComponent instanceof HtmlDataTable) {
            return "after".equals(((HtmlDataTable) uiComponent).getDetailStampLocation());
        }

        return true;
    }

    protected void endTable(FacesContext facesContext, UIComponent uiComponent) throws IOException {
        boolean embedded = isEmbeddedTable(uiComponent);

        if (!embedded) {
            super.endTable(facesContext, uiComponent);
        }
    }

    protected void beforeRow(FacesContext facesContext, UIData uiData) throws IOException {
        super.beforeRow(facesContext, uiData);

        if (!isDetailStampAfterRow(uiData)) {
            renderDetailRow(facesContext, uiData);
        }
    }

    protected void afterRow(FacesContext facesContext, UIData uiData) throws IOException {
        super.afterRow(facesContext, uiData);

        if (isDetailStampAfterRow(uiData)) {
            renderDetailRow(facesContext, uiData);
        }
    }

    /**
     * @param facesContext
     * @param uiData
     * @throws IOException
     */
    private void renderDetailRow(FacesContext facesContext, UIData uiData) throws IOException {
        UIComponent detailStampFacet = uiData.getFacet(DETAIL_STAMP_FACET_NAME);

        if (uiData instanceof HtmlDataTable) {
            HtmlDataTable htmlDataTable = (HtmlDataTable) uiData;

            if (htmlDataTable.isCurrentDetailExpanded()) {

                boolean embedded = false;
                if (detailStampFacet != null) {
                    embedded = isEmbeddedTable(detailStampFacet);
                }

                ResponseWriter writer = facesContext.getResponseWriter();

                if (!embedded) {
                    writer.startElement(HTML.TR_ELEM, uiData);
                    writer.startElement(HTML.TD_ELEM, uiData);
                    //TOMAHAWK-1087 datatable dont renders a detail correct 
                    //if a UIColumns is used we have to count UIColumns 
                    //elements as component.getRowCount()
                    //instead of just get the number of children available,
                    //so the colspan could be assigned correctly.
                    int childCount = 0;
                    for (Iterator childIter = uiData.getChildren().iterator();
                        childIter.hasNext();)
                    {
                        UIComponent childComp = (UIComponent) childIter.next();
                        if (childComp instanceof UIColumns)
                        {
                            UIColumns v = (UIColumns) childComp;
                            childCount += v.getRowCount();
                        }
                        else
                        {
                            childCount++;
                        }
                    }
                    writer.writeAttribute(HTML.COLSPAN_ATTR, new Integer(
                            childCount), null);
                }

                if (detailStampFacet != null) {
                    RendererUtils.renderChild(facesContext, detailStampFacet);
                }

                if (!embedded) {
                    writer.endElement(HTML.TD_ELEM);
                    writer.endElement(HTML.TR_ELEM);
                }
            }
        }
    }

    /**
     * @see org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlTableRendererBase#encodeBegin(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
     */
    public void encodeBegin(FacesContext facesContext, UIComponent uiComponent) throws IOException {
        if (uiComponent instanceof HtmlDataTable) {
            HtmlDataTable htmlDataTable = (HtmlDataTable) uiComponent;
            if (htmlDataTable.isRenderedIfEmpty() || htmlDataTable.getRowCount() > 0) {
                super.encodeBegin(facesContext, uiComponent);
            }
        }
        else {
            super.encodeBegin(facesContext, uiComponent);
        }
    }

    /**
     * @see org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlTableRendererBase#encodeChildren(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
     */
    public void encodeChildren(FacesContext facesContext, UIComponent component) throws IOException {
        if (component instanceof HtmlDataTable) {
            HtmlDataTable htmlDataTable = (HtmlDataTable) component;
            if (htmlDataTable.isRenderedIfEmpty() || htmlDataTable.getRowCount() > 0) {
                super.encodeChildren(facesContext, component);
            }
        }
        else {
            super.encodeChildren(facesContext, component);
        }
    }

    private boolean isGroupedTable(UIData uiData) {
        if (uiData instanceof HtmlDataTable) {
            List children = getChildren(uiData);
            for (int j = 0, size = getChildCount(uiData); j < size; j++) {
                UIComponent child = (UIComponent) children.get(j);
                if (child instanceof HtmlSimpleColumn) {
                    HtmlSimpleColumn column = (HtmlSimpleColumn) child;
                    if (column.isGroupBy()) {
                        return true;
                    }
                }
            }
        }

        return false;  //To change body of created methods use File | Settings | File Templates.
    }

    protected void beforeBody(FacesContext facesContext, UIData uiData) throws IOException {
        if (isGroupedTable(uiData)) {
            createColumnInfos((HtmlDataTable) uiData, facesContext);
        }
        super.beforeBody(facesContext, uiData);
    }

    private void createColumnInfos(HtmlDataTable htmlDataTable, FacesContext facesContext)
        throws IOException {
        int first = htmlDataTable.getFirst();
        int rows = htmlDataTable.getRows();
        int last;
        int currentRowSpan = -1;
        int currentRowInfoIndex = -1;

        TableContext tableContext = htmlDataTable.getTableContext();
        RowInfo rowInfo = null;
        ColumnInfo columnInfo = null;
        HtmlSimpleColumn currentColumn = null;
        Map groupHashTable = new HashMap();

        if (rows <= 0) {
            last = htmlDataTable.getRowCount();
        }
        else {
            last = first + rows;
        }

        //Loop over the Children Columns to find the Columns with groupBy Attribute true
        List children = getChildren(htmlDataTable);
        int nChildren = getChildCount(htmlDataTable);

        for (int j = 0, size = nChildren; j < size; j++) {
            UIComponent child = (UIComponent) children.get(j);
            if (child instanceof HtmlSimpleColumn) {
                currentColumn = (HtmlSimpleColumn) child;
                if (currentColumn.isGroupBy()) {
                    groupHashTable.put(new Integer(j), null);
                }
            }
        }

        boolean groupEndReached = false;

        for (int rowIndex = first; last == -1 || rowIndex < last; rowIndex++) {
            htmlDataTable.setRowIndex(rowIndex);
            rowInfo = new RowInfo();
            //scrolled past the last row
            if (!htmlDataTable.isRowAvailable()) {
                break;
            }

            Set groupIndexList = groupHashTable.keySet();
            List currentColumnContent = null;
            for (Iterator it = groupIndexList.iterator(); it.hasNext();) {
                currentColumnContent = new ArrayList();
                Integer currentIndex = (Integer) it.next();
                currentColumn = (HtmlSimpleColumn) children.get(currentIndex.intValue());

                if (currentColumn.isGroupByValueSet()) {
                    currentColumnContent.add(currentColumn.getGroupByValue());
                }
                else {
                    // iterate the children - this avoids to add the column facet too
                    List currentColumnChildren = currentColumn.getChildren();
                    if (currentColumnChildren != null) {
                        collectChildrenValues(currentColumnContent, currentColumnChildren.iterator());
                    }
                }

                if (!isListEqual(currentColumnContent, (List) groupHashTable.get(currentIndex)) &&
                    currentRowInfoIndex > -1) {
                    groupEndReached = true;
                    groupHashTable.put(currentIndex, currentColumnContent);
                }
                else if (currentRowInfoIndex == -1) {
                    groupHashTable.put(currentIndex, currentColumnContent);
                }
            }
            currentRowSpan++;


            for (int j = 0, size = nChildren; j < size; j++) {
                columnInfo = new ColumnInfo();
                if (groupHashTable.containsKey(new Integer(j)))  // Column is groupBy
                {
                    if (currentRowSpan > 0) {
                        if (groupEndReached) {
                            ((ColumnInfo)
                                ((RowInfo)
                                    tableContext.getRowInfos().get(currentRowInfoIndex - currentRowSpan + 1)).
                                    getColumnInfos().get(j)).
                                setRowSpan(currentRowSpan);
                            columnInfo.setStyle(htmlDataTable.getRowGroupStyle());
                            columnInfo.setStyleClass(htmlDataTable.getRowGroupStyleClass());
                        }
                        else {
                            columnInfo.setRendered(false);
                        }
                    }
                    else {
                        columnInfo.setStyle(htmlDataTable.getRowGroupStyle());
                        columnInfo.setStyleClass(htmlDataTable.getRowGroupStyleClass());
                    }

                }
                else    // Column  is not group by
                {
                    if (groupEndReached) {
                        ((ColumnInfo)
                            ((RowInfo)
                                tableContext.getRowInfos().get(currentRowInfoIndex)).
                                getColumnInfos().get(j)).
                            setStyle(htmlDataTable.getRowGroupStyle());
                        ((ColumnInfo)
                            ((RowInfo)
                                tableContext.getRowInfos().get(currentRowInfoIndex)).
                                getColumnInfos().get(j)).
                            setStyleClass(htmlDataTable.getRowGroupStyleClass());
                    }
                }
                rowInfo.getColumnInfos().add(columnInfo);
            }
            if (groupEndReached) {
                currentRowSpan = 0;
                groupEndReached = false;
            }
            tableContext.getRowInfos().add(rowInfo);
            currentRowInfoIndex++;
        }

        // do further processing if we've found at least one row
        if (currentRowInfoIndex > -1) {
            for (int j = 0, size = nChildren; j < size; j++) {
                if (groupHashTable.containsKey(new Integer(j)))  // Column is groupBy
                {
                    ((ColumnInfo)
                        ((RowInfo)
                            tableContext.getRowInfos().get(currentRowInfoIndex - currentRowSpan)).
                            getColumnInfos().get(j)).
                        setRowSpan(currentRowSpan + 1);
                }
                else    // Column  is not group by
                {
                    ((ColumnInfo)
                        ((RowInfo)
                            tableContext.getRowInfos().get(currentRowInfoIndex)).
                            getColumnInfos().get(j)).
                        setStyle(htmlDataTable.getRowGroupStyle());
                    ((ColumnInfo)
                        ((RowInfo)
                            tableContext.getRowInfos().get(currentRowInfoIndex)).
                            getColumnInfos().get(j)).
                        setStyleClass(htmlDataTable.getRowGroupStyleClass());
                }
            }
        }

        htmlDataTable.setRowIndex(-1);
    }

    protected void collectChildrenValues(List container, Iterator iterChildren) {
        while (iterChildren.hasNext()) {
            UIComponent child = (UIComponent) iterChildren.next();
            if (child.isRendered()) {
                if (child instanceof ValueHolder) {
                    Object value = ((ValueHolder) child).getValue();
                    container.add(value);
                }

                // we lave the column ... now iterate the facets too
                collectChildrenValues(container, child.getFacetsAndChildren());
            }
        }
    }

    /**
     * checks if the contenta of both lists are the same.
* Notice: In case both lists are null or empty they are * considered NOT being equal */ protected boolean isListEqual(List list1, List list2) { if (list1 == list2) { return list1 != null && list1.size() > 0; } if (list1 == null || list2 == null || list1.size() != list2.size()) { return false; } for (int i = 0; i < list1.size(); i++) { Object o1 = list1.get(i); Object o2 = list2.get(i); if (o1 != null && !o1.equals(o2)) { return false; } if (o2 != null && !o2.equals(o1)) { return false; } } return true; } /** * @see org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlTableRendererBase#encodeEnd(javax.faces.context.FacesContext, javax.faces.component.UIComponent) */ public void encodeEnd(FacesContext facesContext, UIComponent uiComponent) throws IOException { if (uiComponent instanceof HtmlDataTable) { HtmlDataTable htmlDataTable = (HtmlDataTable) uiComponent; if (htmlDataTable.isRenderedIfEmpty() || htmlDataTable.getRowCount() > 0) { super.encodeEnd(facesContext, uiComponent); } } else { super.encodeEnd(facesContext, uiComponent); } } protected void renderRowStart(FacesContext facesContext, ResponseWriter writer, UIData uiData, Styles styles, int rowStyleIndex) throws IOException { super.renderRowStart(facesContext, writer, uiData, styles, rowStyleIndex); // get event handlers from component HtmlDataTable table = (HtmlDataTable) uiData; renderRowAttribute(writer, HTML.ONCLICK_ATTR, table.getRowOnClick()); renderRowAttribute(writer, HTML.ONDBLCLICK_ATTR, table.getRowOnDblClick()); renderRowAttribute(writer, HTML.ONKEYDOWN_ATTR, table.getRowOnKeyDown()); renderRowAttribute(writer, HTML.ONKEYPRESS_ATTR, table.getRowOnKeyPress()); renderRowAttribute(writer, HTML.ONKEYUP_ATTR, table.getRowOnKeyUp()); renderRowAttribute(writer, HTML.ONMOUSEDOWN_ATTR, table.getRowOnMouseDown()); renderRowAttribute(writer, HTML.ONMOUSEMOVE_ATTR, table.getRowOnMouseMove()); renderRowAttribute(writer, HTML.ONMOUSEOUT_ATTR, table.getRowOnMouseOut()); renderRowAttribute(writer, HTML.ONMOUSEOVER_ATTR, table.getRowOnMouseOver()); renderRowAttribute(writer, HTML.ONMOUSEUP_ATTR, table.getRowOnMouseUp()); } /** * @see org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlTableRendererBase#renderRowStyle(javax.faces.context.FacesContext, javax.faces.context.ResponseWriter, javax.faces.component.UIData, org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlTableRendererBase.Styles, int) */ protected void renderRowStyle(FacesContext facesContext, ResponseWriter writer, UIData uiData, Styles styles, int rowStyleIndex) throws IOException { String rowStyleClass; String rowStyle; if (uiData instanceof HtmlDataTable) { HtmlDataTable datatable = (HtmlDataTable) uiData; rowStyleClass = datatable.getRowStyleClass(); rowStyle = datatable.getRowStyle(); } else { rowStyleClass = (String) uiData.getAttributes().get(JSFAttr.ROW_STYLECLASS_ATTR); rowStyle = (String) uiData.getAttributes().get(JSFAttr.ROW_STYLE_ATTR); } if (rowStyleClass == null) { super.renderRowStyle(facesContext, writer, uiData, styles, rowStyleIndex); } else if (rowStyleClass != null && rowStyleClass.length() <= 0) { // TOMAHAWK-1628 rowStyleClass can hold an EL that return null and is coerced to empty string super.renderRowStyle(facesContext, writer, uiData, styles, rowStyleIndex); } else { writer.writeAttribute(HTML.CLASS_ATTR, rowStyleClass, null); } if (rowStyle != null) { writer.writeAttribute(HTML.STYLE_ATTR, rowStyle, null); } } protected void renderRowAttribute(ResponseWriter writer, String htmlAttribute, Object value) throws IOException { if (value != null) { writer.writeAttribute(htmlAttribute, value, null); } } /** * Render the specified column object using the current row data. *

* When the component is a UIColumn object, the inherited method is * invoked to render a single table cell. *

* In addition to the inherited functionality, support is implemented * here for UIColumns children. When a UIColumns child is encountered: *

     * For each dynamic column in that UIColumns child:
     *   * Select the column (which sets variable named by the var attribute
     *     to refer to the current column object)
     *   * Call this.renderColumnBody passing the UIColumns object.
     * 
* The renderColumnBody method eventually: *
    *
  • emits TD *
  • calls encodeBegin on the UIColumns (which does nothing) *
  • calls rendering methods on all children of the UIColumns *
  • calls encodeEnd on the UIColumns (which does nothing) *
  • emits /TD *
* If the children of the UIColumns access the variable named by the var * attribute on the UIColumns object, then they end up rendering content * that is extracted from the current column object. * * @see org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlTableRendererBase#encodeColumnChild(javax.faces.context.FacesContext, javax.faces.context.ResponseWriter, javax.faces.component.UIData, javax.faces.component.UIComponent, org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlTableRendererBase.Styles, int) */ protected void encodeColumnChild(FacesContext facesContext, ResponseWriter writer, UIData uiData, UIComponent component, Styles styles, int columnStyleIndex) throws IOException { //columnStyleIndex param does not takes into //consideration UIColumns, since it is called from HtmlTableRendererBase. //So we need to recalculate its index taking into account that //UIColumns component count as ((UIColumns) child).getRowCount() instead 1 columnStyleIndex = getColumnStyleIndex(uiData, columnStyleIndex); super.encodeColumnChild(facesContext, writer, uiData, component, styles, columnStyleIndex); if (component instanceof UIColumns) { UIColumns columns = (UIColumns) component; for (int k = 0, colSize = columns.getRowCount(); k < colSize; k++) { columns.setRowIndex(k); renderColumnBody(facesContext, writer, uiData, component, styles, columnStyleIndex + k); } columns.setRowIndex(-1); } } /** * This method calculates the correct columnStyleIndex taking the dynamic columns * of UIColumns into consideration * * @param uiData * @param columnStyleIndex * @return the correct columnStyleIndex */ private int getColumnStyleIndex(UIData uiData, int columnStyleIndex) { int colStyleIndex = 0; for (int i = 0; i < columnStyleIndex; i++) { UIComponent child = (UIComponent) uiData.getChildren().get(i % uiData.getChildCount()); if (child instanceof UIColumns) { colStyleIndex += ((UIColumns) child).getRowCount(); continue; } colStyleIndex++; } return colStyleIndex; } /** * @see org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlTableRendererBase#renderColumnBody(javax.faces.context.FacesContext, javax.faces.context.ResponseWriter, javax.faces.component.UIData, javax.faces.component.UIComponent, org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlTableRendererBase.Styles, int) */ protected void renderColumnBody(FacesContext facesContext, ResponseWriter writer, UIData uiData, UIComponent component, Styles styles, int columnStyleIndex) throws IOException { if (isGroupedTable(uiData)) { HtmlDataTable htmlDataTable = (HtmlDataTable) uiData; List tableChildren = htmlDataTable.getChildren(); int first = htmlDataTable.getFirst(); int rowInfoIndex = htmlDataTable.getRowIndex() - first; int columnInfoIndex = tableChildren.indexOf(component); RowInfo rowInfo = (RowInfo) htmlDataTable.getTableContext().getRowInfos().get(rowInfoIndex); ColumnInfo columnInfo = (ColumnInfo) rowInfo.getColumnInfos().get(columnInfoIndex); if (!columnInfo.isRendered()) { return; } if (component instanceof HtmlColumn && amISpannedOver(null, component)) { return; } writer.startElement(HTML.TD_ELEM, uiData); String styleClass = null; if (component instanceof HtmlColumn) { styleClass = ((HtmlColumn) component).getStyleClass(); } if (columnInfo.getStyleClass() != null) { styleClass = columnInfo.getStyleClass(); } if (styles.hasColumnStyle()) { if (styleClass == null) { styleClass = styles.getColumnStyle(columnStyleIndex); } } if (styleClass != null) { writer.writeAttribute(HTML.CLASS_ATTR, styleClass, null); } if (columnInfo.getStyle() != null) { writer.writeAttribute(HTML.STYLE_ATTR, columnInfo.getStyle(), null); } if (columnInfo.getRowSpan() > 1) { writer.writeAttribute("rowspan", new Integer(columnInfo.getRowSpan()).toString(), null); if (columnInfo.getStyle() == null) { writer.writeAttribute(HTML.STYLE_ATTR, "vertical-align:top", null); } } renderHtmlColumnAttributes(writer, component, null); RendererUtils.renderChild(facesContext, component); writer.endElement(HTML.TD_ELEM); } else if (component instanceof HtmlColumn) { if (amISpannedOver(null, component)) { return; } writer.startElement(HTML.TD_ELEM, uiData); String styleClass = ((HtmlColumn) component).getStyleClass(); if (styles.hasColumnStyle()) { if (styleClass == null) { styleClass = styles.getColumnStyle(columnStyleIndex); } } if (styleClass != null) { writer.writeAttribute(HTML.CLASS_ATTR, styleClass, null); } renderHtmlColumnAttributes(writer, component, null); RendererUtils.renderChild(facesContext, component); writer.endElement(HTML.TD_ELEM); } else { super.renderColumnBody(facesContext, writer, uiData, component, styles, columnStyleIndex); } } /** * Render the header or footer of the specified column object. *

* When the component is a UIColumn object, the inherited method is * invoked to render a single header cell. *

* In addition to the inherited functionality, support is implemented * here for UIColumns children. When a UIColumns child is encountered: *

     * For each dynamic column in that UIColumns child:
     *   * Select the column (which sets variable named by the var attribute
     *     to refer to the current column object)
     *   * Call this.renderColumnHeaderCell or this.renderColumnFooterCell
     *     passing the header or footer facet of the UIColumns object.
     * 
* If the facet of the UIColumns accesses the variable named by the var * attribute on the UIColumns object, then it ends up rendering content * that is extracted from the current column object. * * @see org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlTableRendererBase#renderColumnChildHeaderOrFooterRow(javax.faces.context.FacesContext, javax.faces.context.ResponseWriter, javax.faces.component.UIComponent, java.lang.String, boolean) */ protected void renderColumnChildHeaderOrFooterRow( FacesContext facesContext, ResponseWriter writer, UIComponent uiComponent, String styleClass, boolean header) throws IOException { super.renderColumnChildHeaderOrFooterRow(facesContext, writer, uiComponent, styleClass, header); if (uiComponent instanceof UIColumns) { UIColumns columns = (UIColumns) uiComponent; for (int i = 0, size = columns.getRowCount(); i < size; i++) { columns.setRowIndex(i); if (header) { renderColumnHeaderCell(facesContext, writer, columns, columns.getHeader(), styleClass, 0); } else { renderColumnFooterCell(facesContext, writer, columns, columns.getFooter(), styleClass, 0); } } columns.setRowIndex(-1); } } /** * @see org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlTableRendererBase#renderColumnHeaderCell(javax.faces.context.FacesContext, javax.faces.context.ResponseWriter, javax.faces.component.UIComponent, javax.faces.component.UIComponent, java.lang.String, int) */ protected void renderColumnHeaderCell(FacesContext facesContext, ResponseWriter writer, UIComponent uiComponent, UIComponent facet, String headerStyleClass, int colspan) throws IOException { if (uiComponent instanceof HtmlColumn) { HtmlColumn column = (HtmlColumn) uiComponent; if (amISpannedOver("header", uiComponent)) { return; } writer.startElement(determineHeaderCellTag(facesContext, uiComponent.getParent()), uiComponent); String columnId = column.getColumnId(); if (columnId != null) { writer.writeAttribute(HTML.ID_ATTR, columnId, null); } if (colspan > 1) { writer.writeAttribute(HTML.COLSPAN_ATTR, new Integer(colspan), null); } String styleClass = ((HtmlColumn) uiComponent) .getHeaderstyleClass(); if (styleClass == null) { styleClass = headerStyleClass; } if (styleClass != null) { writer.writeAttribute(HTML.CLASS_ATTR, styleClass, null); } renderHtmlColumnAttributes(writer, uiComponent, "header"); if (facet != null) { RendererUtils.renderChild(facesContext, facet); } writer.endElement(determineHeaderCellTag(facesContext, uiComponent.getParent())); } else { super.renderColumnHeaderCell(facesContext, writer, uiComponent, facet, headerStyleClass, colspan); } } /** * @see org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlTableRendererBase#renderColumnFooterCell(javax.faces.context.FacesContext, javax.faces.context.ResponseWriter, javax.faces.component.UIComponent, javax.faces.component.UIComponent, java.lang.String, int) */ protected void renderColumnFooterCell(FacesContext facesContext, ResponseWriter writer, UIComponent uiComponent, UIComponent facet, String footerStyleClass, int colspan) throws IOException { if (uiComponent instanceof HtmlColumn) { if (amISpannedOver("footer", uiComponent)) { return; } writer.startElement(HTML.TD_ELEM, uiComponent); if (colspan > 1) { writer.writeAttribute(HTML.COLSPAN_ATTR, new Integer(colspan), null); } String styleClass = ((HtmlColumn) uiComponent) .getFooterstyleClass(); if (styleClass == null) { styleClass = footerStyleClass; } if (styleClass != null) { writer.writeAttribute(HTML.CLASS_ATTR, styleClass, null); } renderHtmlColumnAttributes(writer, uiComponent, "footer"); if (facet != null) { RendererUtils.renderChild(facesContext, facet); } writer.endElement(HTML.TD_ELEM); } else { super.renderColumnFooterCell(facesContext, writer, uiComponent, facet, footerStyleClass, colspan); } } protected void renderHtmlColumnAttributes(ResponseWriter writer, UIComponent uiComponent, String prefix) throws IOException { String[] attrs = (String[]) ArrayUtils.concat(HTML.COMMON_PASSTROUGH_ATTRIBUTES_WITHOUT_STYLE, new String[]{HTML.COLSPAN_ATTR}); for (int i = 0, size = attrs.length; i < size; i++) { String attributeName = attrs[i]; String compAttrName = prefix != null ? prefix + attributeName : attributeName; HtmlRendererUtils.renderHTMLAttribute(writer, uiComponent, compAttrName, attributeName); } String compAttrName = prefix != null ? prefix + HTML.STYLE_ATTR : HTML.STYLE_ATTR; HtmlRendererUtils.renderHTMLAttribute(writer, uiComponent, compAttrName, HTML.STYLE_ATTR); HtmlRendererUtils.renderHTMLAttribute(writer, uiComponent, HTML.WIDTH_ATTR, HTML.WIDTH_ATTR); } /** * Return the number of columns spanned by the specified component. *

* For normal components, use the inherited implementation. * For UIColumns children, return the number of dynamic columns rendered * by that child. * * @see org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlTableRendererBase * #determineChildColSpan(javax.faces.component.UIComponent) */ protected int determineChildColSpan(UIComponent uiComponent) { int result = super.determineChildColSpan(uiComponent); if (uiComponent instanceof UIColumns) { result += ((UIColumns) uiComponent).getRowCount(); } return result; } /** * Return true if the specified component has a facet that needs to be * rendered in a THEAD or TFOOT section. * * @see org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlTableRendererBase#hasFacet(boolean, javax.faces.component.UIComponent) */ protected boolean hasFacet(boolean header, UIComponent uiComponent) { boolean result = super.hasFacet(header, uiComponent); if (!result && uiComponent instanceof UIColumns) { // Why is this necessary? It seems to me that the inherited // implementation will work fine with a UIColumns component... UIColumns columns = (UIColumns) uiComponent; result = header ? columns.getHeader() != null : columns.getFooter() != null; } return result; } /** * Renders the column footer. * Rendering will be supressed if all of the facets have rendered="false" */ protected void renderColumnFooterRow(FacesContext facesContext, ResponseWriter writer, UIComponent component, String footerStyleClass) throws IOException { if (determineRenderFacet(component, false)) { super.renderColumnFooterRow(facesContext, writer, component, footerStyleClass); } } /** * Renders the column header. * Rendering will be supressed if all of the facets have rendered="false" */ protected void renderColumnHeaderRow(FacesContext facesContext, ResponseWriter writer, UIComponent component, String headerStyleClass) throws IOException { if (determineRenderFacet(component, true)) { super.renderColumnHeaderRow(facesContext, writer, component, headerStyleClass); } } /** * determine if the header or footer should be rendered. */ protected boolean determineRenderFacet(UIComponent component, boolean header) { for (Iterator it = getChildren(component).iterator(); it.hasNext();) { UIComponent uiComponent = (UIComponent) it.next(); if (uiComponent.isRendered() && determineChildColSpan(uiComponent) > 0) { UIComponent facet = header ? (UIComponent) uiComponent.getFacets().get(HEADER_FACET_NAME) : (UIComponent) uiComponent.getFacets().get(FOOTER_FACET_NAME); if (facet != null && facet.isRendered()) { return true; } } } return false; } protected void beforeColumn(FacesContext facesContext, UIData uiData, int columnIndex) throws IOException { super.beforeColumn(facesContext, uiData, columnIndex); if (uiData instanceof HtmlDataTable) { HtmlDataTable dataTable = (HtmlDataTable) uiData; putSortedReqScopeParam(facesContext, dataTable, columnIndex); } } protected void beforeColumnHeaderOrFooter(FacesContext facesContext, UIData uiData, boolean header, int columnIndex) throws IOException { super.beforeColumnHeaderOrFooter(facesContext, uiData, header, columnIndex); if (header && uiData instanceof HtmlDataTable) { HtmlDataTable dataTable = (HtmlDataTable) uiData; putSortedReqScopeParam(facesContext, dataTable, columnIndex); } } protected void putSortedReqScopeParam(FacesContext facesContext, HtmlDataTable dataTable, int columnIndex) { String sortedColumnVar = dataTable.getSortedColumnVar(); Map requestMap = facesContext.getExternalContext().getRequestMap(); if (columnIndex == dataTable.getSortColumnIndex()) { if (sortedColumnVar != null) { requestMap.put(sortedColumnVar, Boolean.TRUE); } } else if (sortedColumnVar != null) { requestMap.remove(sortedColumnVar); } } /** * specify if the header, footer or is spanned over (not shown) because * of a colspan in a cell in a previous column * * @param prefix header, footer or null * @param component */ protected boolean amISpannedOver(String prefix, UIComponent component) { UIComponent table = component.getParent(); int span = 0; for (Iterator it = table.getChildren().iterator(); it.hasNext();) { UIComponent columnComponent = (UIComponent) it.next(); if (!(columnComponent instanceof HtmlColumn)) { continue; } if (span > 0) { span--; } if (columnComponent == component) { return span > 0; } if (span == 0) { try { if (prefix == null && ((HtmlColumn) columnComponent).getColspan() != null) { span = Integer.parseInt(((HtmlColumn) columnComponent).getColspan()); } if ("header".equals(prefix) && ((HtmlColumn) columnComponent).getHeadercolspan() != null) { span = Integer.parseInt(((HtmlColumn) columnComponent).getHeadercolspan()); } if ("footer".equals(prefix) && ((HtmlColumn) columnComponent).getFootercolspan() != null) { span = Integer.parseInt(((HtmlColumn) columnComponent).getFootercolspan()); } } catch (NumberFormatException ex) { log.warn("Invalid " + ((prefix == null) ? "" : prefix) + "colspan attribute ignored"); } } } return false; } /** * Perform any operations necessary in the TBODY start tag. * * @param facesContext the FacesContext. * @param uiData the UIData being rendered. */ protected void inBodyStart(FacesContext facesContext, UIData uiData) throws IOException { String bodyStyleClass; String bodyStyle; if (uiData instanceof HtmlDataTable) { bodyStyleClass = ((HtmlDataTable) uiData).getBodyStyleClass(); bodyStyle = ((HtmlDataTable) uiData).getBodyStyle(); } else { bodyStyleClass = (String) uiData.getAttributes().get(BODY_STYLE_CLASS); bodyStyle = (String) uiData.getAttributes().get(BODY_STYLE); } ResponseWriter writer = facesContext.getResponseWriter(); if (bodyStyleClass != null) { writer.writeAttribute(HTML.CLASS_ATTR, bodyStyleClass, BODY_STYLE_CLASS); } if (bodyStyle != null) { writer.writeAttribute(HTML.STYLE_ATTR, bodyStyle, BODY_STYLE); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy