You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by lu...@apache.org on 2010/06/17 04:01:40 UTC

svn commit: r955454 - in /myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/newspaper: ./ HtmlNewspaperTableRenderer.java

Author: lu4242
Date: Thu Jun 17 02:01:40 2010
New Revision: 955454

URL: http://svn.apache.org/viewvc?rev=955454&view=rev
Log:
TOMAHAWK-1474 Behavior support for components that contains event aware properties in jsf 2.0 module

Added:
    myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/newspaper/
    myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/newspaper/HtmlNewspaperTableRenderer.java

Added: myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/newspaper/HtmlNewspaperTableRenderer.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/newspaper/HtmlNewspaperTableRenderer.java?rev=955454&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/newspaper/HtmlNewspaperTableRenderer.java (added)
+++ myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/newspaper/HtmlNewspaperTableRenderer.java Thu Jun 17 02:01:40 2010
@@ -0,0 +1,425 @@
+/*
+ * 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.custom.newspaper;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.component.behavior.ClientBehavior;
+import javax.faces.component.behavior.ClientBehaviorHolder;
+import javax.faces.component.html.HtmlDataTable;
+import javax.faces.context.ResponseWriter;
+import javax.faces.component.UIColumn;
+import javax.faces.component.UIData;
+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.renderkit.html.util.ResourceUtils;
+import org.apache.myfaces.shared_tomahawk.util.ArrayUtils;
+import org.apache.myfaces.shared_tomahawk.util.StringUtils;
+
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Renderer for a table in multiple balanced columns.
+ *
+ * @JSFRenderer
+ *   renderKitId = "HTML_BASIC" 
+ *   family = "javax.faces.Data"
+ *   type = "org.apache.myfaces.HtmlNewspaperTable"
+ *
+ * @author <a href="mailto:jesse@odel.on.ca">Jesse Wilson</a>
+ */
+public class HtmlNewspaperTableRenderer
+        extends HtmlTableRendererBase
+{
+    private static final Log log = LogFactory.getLog(HtmlNewspaperTableRenderer.class);
+
+    public void encodeBegin(FacesContext facesContext, UIComponent uiComponent) throws IOException {
+        RendererUtils.checkParamValidity(facesContext, uiComponent, UIData.class);
+        ResponseWriter writer = facesContext.getResponseWriter();
+        HtmlNewspaperTable newspaperTable = (HtmlNewspaperTable)uiComponent;
+        
+        Map<String, List<ClientBehavior>> behaviors = null;
+        if (uiComponent instanceof ClientBehaviorHolder)
+        {
+            behaviors = ((ClientBehaviorHolder) uiComponent).getClientBehaviors();
+            if (!behaviors.isEmpty())
+            {
+                ResourceUtils.renderDefaultJsfJsInlineIfNecessary(facesContext, facesContext.getResponseWriter());
+            }
+        }
+        
+        // write out the table start tag
+        HtmlRendererUtils.writePrettyLineSeparator(facesContext);
+        writer.startElement(HTML.TABLE_ELEM, newspaperTable);
+        writer.writeAttribute(HTML.ID_ATTR, newspaperTable.getClientId(facesContext), null);
+        
+        if (behaviors != null && !behaviors.isEmpty())
+        {
+            HtmlRendererUtils.renderBehaviorizedEventHandlers(facesContext, writer, newspaperTable, behaviors);
+            HtmlRendererUtils.renderHTMLAttributes(writer, newspaperTable, HTML.TABLE_PASSTHROUGH_ATTRIBUTES_WITHOUT_EVENTS); 
+            
+        }
+        else
+        {
+            HtmlRendererUtils.renderHTMLAttributes(writer, newspaperTable, HTML.TABLE_PASSTHROUGH_ATTRIBUTES);
+        }
+
+        // render the header
+        renderFacet(facesContext, writer, newspaperTable, true);
+    }
+    
+    public void encodeChildren(FacesContext facesContext, UIComponent uiComponent) throws IOException {
+        RendererUtils.checkParamValidity(facesContext, uiComponent, UIData.class);
+        ResponseWriter writer = facesContext.getResponseWriter();
+        HtmlNewspaperTable newspaperTable = (HtmlNewspaperTable)uiComponent;
+        
+        // begin the table
+        HtmlRendererUtils.writePrettyLineSeparator(facesContext);
+        writer.startElement(HTML.TBODY_ELEM, newspaperTable);
+        
+        // get the CSS styles
+        Styles styles = getStyles(newspaperTable);
+
+        // count the number of actual rows
+        int first = newspaperTable.getFirst();
+        int rows = newspaperTable.getRows();
+        int rowCount = newspaperTable.getRowCount();
+        if(rows <= 0) {
+            rows = rowCount - first;
+        }
+        int last = first + rows;
+        if(last > rowCount) last = rowCount;
+        
+        // the number of slices to break the table up into */
+        int newspaperColumns = newspaperTable.getNewspaperColumns();
+        int newspaperRows;
+        if((last - first) % newspaperColumns == 0) newspaperRows = (last - first) / newspaperColumns;
+        else newspaperRows = ((last - first) / newspaperColumns) + 1;
+
+        // walk through the newspaper rows
+        for(int nr = 0; nr < newspaperRows; nr++) {
+
+            // write the row start
+            HtmlRendererUtils.writePrettyLineSeparator(facesContext);
+            writer.startElement(HTML.TR_ELEM, newspaperTable);
+            if(styles.hasRowStyle()) {
+                String rowStyle = styles.getRowStyle(nr);
+                writer.writeAttribute(HTML.CLASS_ATTR, rowStyle, null);
+            }
+
+            // walk through the newspaper columns
+            for(int nc = 0; nc < newspaperColumns; nc++) {
+
+                // the current row in the 'real' table
+                int currentRow = nc * newspaperRows + nr + first;
+                
+                // if this row is not to be rendered
+                if(currentRow >= last) continue;
+
+                // bail if any row does not exist
+                newspaperTable.setRowIndex(currentRow);
+                if(!newspaperTable.isRowAvailable()) {
+                    log.error("Row is not available. Rowindex = " + currentRow);
+                    return;
+                }
+    
+                // write each cell
+                List children = newspaperTable.getChildren();
+                for(int j = 0; j < newspaperTable.getChildCount(); j++) {
+                    // skip this child if its not a rendered column 
+                    UIComponent child = (UIComponent)children.get(j);
+                    if(!(child instanceof UIColumn)) continue;
+                    if(!child.isRendered()) continue;
+                    // draw the element's cell
+                    writer.startElement(HTML.TD_ELEM, newspaperTable);
+                    if(styles.hasColumnStyle()) writer.writeAttribute(HTML.CLASS_ATTR, styles.getColumnStyle(nc * newspaperTable.getChildCount() + j), null);
+                    RendererUtils.renderChild(facesContext, child);
+                    writer.endElement(HTML.TD_ELEM);
+                }
+
+                // draw the spacer facet
+                if(nc < newspaperColumns - 1) renderSpacerCell(facesContext, writer, newspaperTable);
+            }
+            // write the row end
+            writer.endElement(HTML.TR_ELEM);
+        }
+        
+        // write the end of the table's body
+        writer.endElement(HTML.TBODY_ELEM);
+    }
+    
+    /** 
+     * Fetch the number of columns to divide the table into.
+     */
+    private int getNewspaperColumns() {
+        return 3;
+    }
+
+    public void encodeEnd(FacesContext facesContext, UIComponent uiComponent) throws IOException {
+        RendererUtils.checkParamValidity(facesContext, uiComponent, UIData.class);
+        ResponseWriter writer = facesContext.getResponseWriter();
+        HtmlNewspaperTable newspaperTable = (HtmlNewspaperTable)uiComponent;
+        
+        // render the footer
+        renderFacet(facesContext, writer, newspaperTable, false);
+        
+        // write out the table end tag
+        writer.endElement(HTML.TABLE_ELEM);
+        HtmlRendererUtils.writePrettyLineSeparator(facesContext);
+    }
+
+    
+    /**
+     * Count the number of columns in the speicifed Newspaper table..
+     */
+    private int countColumns(HtmlNewspaperTable newspaperTable) {
+        int columnCount = 0;
+        for(Iterator it = newspaperTable.getChildren().iterator(); it.hasNext(); ) {
+            UIComponent uiComponent = (UIComponent)it.next();
+            if (uiComponent instanceof UIColumn && ((UIColumn)uiComponent).isRendered()) {
+                columnCount++;
+            }
+        }
+        return columnCount;
+    }
+    
+    /**
+     * Tests if the specified facet exists for the specified newspaper table.
+     */
+    private boolean hasFacet(HtmlNewspaperTable newspaperTable, boolean header) {
+        for(Iterator it = newspaperTable.getChildren().iterator(); it.hasNext(); ) {
+            // get the column
+            UIComponent uiComponent = (UIComponent)it.next();
+            if(!(uiComponent instanceof UIColumn)) continue;
+            UIColumn column = (UIColumn)uiComponent;
+            if(!column.isRendered()) continue;
+            
+            // test the facet
+            if(header && ((UIColumn)uiComponent).getHeader() != null) return true;
+            if(!header && ((UIColumn)uiComponent).getFooter() != null) return true;
+        }
+        return false;
+    }
+
+    /**
+     * Render table headers and footers.
+     */
+    private void renderFacet(FacesContext facesContext, ResponseWriter writer, HtmlNewspaperTable newspaperTable, boolean header) throws IOException {
+        int columnCount = countColumns(newspaperTable);
+        boolean hasColumnFacet = hasFacet(newspaperTable, header);
+        UIComponent facet = header ? newspaperTable.getHeader() : newspaperTable.getFooter();
+        
+        // quit if there's nothing to draw
+        if(facet == null && !hasColumnFacet) return;
+        
+        // start the row block
+        HtmlRendererUtils.writePrettyLineSeparator(facesContext);
+        String elemName = header ? HTML.THEAD_ELEM : HTML.TFOOT_ELEM;
+        writer.startElement(elemName, newspaperTable);
+        
+        // fetch the style
+        String styleClass;
+        if(header) styleClass = getHeaderClass(newspaperTable);
+        else styleClass = getFooterClass(newspaperTable);
+        
+        // write the header row and column headers
+        if(header) {
+            if (facet != null) renderTableHeaderOrFooterRow(facesContext, writer, newspaperTable, facet, styleClass, HTML.TD_ELEM, columnCount);
+            if (hasColumnFacet) renderColumnHeaderOrFooterRow(facesContext, writer, newspaperTable, styleClass, header);
+        // write the footer row and column footers
+        } else {
+            if (hasColumnFacet) renderColumnHeaderOrFooterRow(facesContext, writer, newspaperTable, styleClass, header);
+            if (facet != null) renderTableHeaderOrFooterRow(facesContext, writer, newspaperTable, facet, styleClass, HTML.TD_ELEM, columnCount);
+        }
+        
+        // end the row block
+        writer.endElement(elemName);
+    }
+    
+    /**
+     * Renders the table header or footer row. This is one giant cell that spans
+     * the entire table header or footer.
+     */
+    private void renderTableHeaderOrFooterRow(FacesContext facesContext, ResponseWriter writer,
+        HtmlNewspaperTable newspaperTable, UIComponent facet, String styleClass, String colElementName, int tableColumns)
+        throws IOException {
+
+        // start the row
+        HtmlRendererUtils.writePrettyLineSeparator(facesContext);
+        writer.startElement(HTML.TR_ELEM, newspaperTable);
+        writer.startElement(colElementName, newspaperTable);
+        if(styleClass != null) writer.writeAttribute(HTML.CLASS_ATTR, styleClass, null);
+        if(colElementName.equals(HTML.TH_ELEM)) writer.writeAttribute(HTML.SCOPE_ATTR, HTML.SCOPE_COLGROUP_VALUE, null);
+
+        // span all the table's columns
+        int totalColumns = newspaperTable.getNewspaperColumns() * tableColumns;
+        if(newspaperTable.getSpacer() != null) totalColumns = totalColumns + getNewspaperColumns() - 1;
+        writer.writeAttribute(HTML.COLSPAN_ATTR, new Integer(totalColumns), null);
+
+        // write the actual cell contents
+        if(facet != null) RendererUtils.renderChild(facesContext, facet);
+        
+        // finish
+        writer.endElement(colElementName);
+        writer.endElement(HTML.TR_ELEM);
+    }
+
+
+    /**
+     * Renders the column header or footer row.
+     */
+    private void renderColumnHeaderOrFooterRow(FacesContext facesContext,
+        ResponseWriter writer, HtmlNewspaperTable newspaperTable, String styleClass, boolean header)
+        throws IOException {
+
+        HtmlRendererUtils.writePrettyLineSeparator(facesContext);
+        writer.startElement(HTML.TR_ELEM, newspaperTable);
+        int newspaperColumns = newspaperTable.getNewspaperColumns();
+        for(int nc = 0; nc < newspaperColumns; nc++) {
+            for(Iterator it = newspaperTable.getChildren().iterator(); it.hasNext(); ) {
+                UIComponent uiComponent = (UIComponent)it.next();
+                if(!(uiComponent instanceof UIColumn)) continue;
+                UIColumn column = (UIColumn)uiComponent;
+                if(!column.isRendered()) continue;
+                // get the component to render
+                UIComponent facet = null;
+                if(header) facet = column.getHeader();
+                else facet = column.getFooter();
+                // do the rendering of the cells
+                renderColumnHeaderOrFooterCell(facesContext, writer, column, styleClass, facet);
+            }
+
+            // draw the spacer facet
+            if(nc < newspaperColumns - 1) renderSpacerCell(facesContext, writer, newspaperTable);
+        }
+        writer.endElement(HTML.TR_ELEM);
+    }
+
+    /**
+     * Renders a cell in the column header or footer.
+     */
+    private void renderColumnHeaderOrFooterCell(FacesContext facesContext, ResponseWriter writer,
+        UIColumn uiColumn, String styleClass, UIComponent facet) throws IOException {
+
+        writer.startElement(HTML.TH_ELEM, uiColumn);
+        if(styleClass != null) writer.writeAttribute(HTML.CLASS_ATTR, styleClass, null);
+        if(facet != null) RendererUtils.renderChild(facesContext, facet);
+        writer.endElement(HTML.TH_ELEM);
+    }
+    
+    /**
+     * Renders a spacer between adjacent newspaper columns.
+     */
+    private void renderSpacerCell(FacesContext facesContext, ResponseWriter writer,
+        HtmlNewspaperTable newspaperTable) throws IOException {
+        if(newspaperTable.getSpacer() == null) return;
+        
+        writer.startElement(HTML.TD_ELEM, newspaperTable);
+        RendererUtils.renderChild(facesContext, newspaperTable.getSpacer());
+        writer.endElement(HTML.TD_ELEM);
+    }
+
+    /**
+     * Gets the style class for the table header.
+     */
+    private static String getHeaderClass(HtmlNewspaperTable newspaperTable) {
+        if(newspaperTable instanceof HtmlDataTable) {
+            return ((HtmlDataTable)newspaperTable).getHeaderClass();
+        } else {
+            return (String)newspaperTable.getAttributes().get(JSFAttr.HEADER_CLASS_ATTR);
+        }
+    }
+    /**
+     * Gets the style class for the table footer.
+     */
+    private static String getFooterClass(HtmlNewspaperTable newspaperTable) {
+        if(newspaperTable instanceof HtmlDataTable) {
+            return ((HtmlDataTable)newspaperTable).getFooterClass();
+        } else {
+            return (String)newspaperTable.getAttributes().get(JSFAttr.FOOTER_CLASS_ATTR);
+        }
+    }
+
+    /**
+     * Gets styles for the specified component.
+     */
+    public static Styles getStyles(HtmlNewspaperTable newspaperTable) {
+        String rowClasses;
+        String columnClasses;
+        if(newspaperTable instanceof HtmlDataTable) {
+            rowClasses = ((HtmlDataTable)newspaperTable).getRowClasses();
+            columnClasses = ((HtmlDataTable)newspaperTable).getColumnClasses();
+        } else {
+            rowClasses = (String)newspaperTable.getAttributes().get(JSFAttr.ROW_CLASSES_ATTR);
+            columnClasses = (String)newspaperTable.getAttributes().get(JSFAttr.COLUMN_CLASSES_ATTR);
+        }
+        return new Styles(rowClasses, columnClasses);
+    }
+
+    /**
+     * Class manages the styles from String lists.
+     */
+    private static class Styles {
+
+        private String[] _columnStyle;
+        private String[] _rowStyle;
+
+        Styles(String rowStyles, String columnStyles) {
+            _rowStyle = (rowStyles == null)
+                ? ArrayUtils.EMPTY_STRING_ARRAY
+                : StringUtils.trim(
+                    StringUtils.splitShortString(rowStyles, ','));
+            _columnStyle = (columnStyles == null)
+                ? ArrayUtils.EMPTY_STRING_ARRAY
+                : StringUtils.trim(
+                    StringUtils.splitShortString(columnStyles, ','));
+        }
+
+        public String getRowStyle(int idx) {
+            if(!hasRowStyle()) {
+                return null;
+            }
+            return _rowStyle[idx % _rowStyle.length];
+        }
+
+        public String getColumnStyle(int idx) {
+            if(!hasColumnStyle()) {
+                return null;
+            }
+            return _columnStyle[idx % _columnStyle.length];
+        }
+
+        public boolean hasRowStyle() {
+            return _rowStyle.length > 0;
+        }
+
+        public boolean hasColumnStyle() {
+            return _columnStyle.length > 0;
+        }
+    }
+}
\ No newline at end of file