View Javadoc

    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one
    3    * or more contributor license agreements.  See the NOTICE file
    4    * distributed with this work for additional information
    5    * regarding copyright ownership.  The ASF licenses this file
    6    * to you under the Apache License, Version 2.0 (the
    7    * "License"); you may not use this file except in compliance
    8    * with the License.  You may obtain a copy of the License at
    9    *
    10   *   http://www.apache.org/licenses/LICENSE-2.0
    11   *
    12   * Unless required by applicable law or agreed to in writing,
    13   * software distributed under the License is distributed on an
    14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    15   * KIND, either express or implied.  See the License for the
    16   * specific language governing permissions and limitations
    17   * under the License.
    18   */
    19  package org.apache.myfaces.shared_orchestra.renderkit.html;
    20
    21  import org.apache.commons.logging.Log;
    22  import org.apache.commons.logging.LogFactory;
    23  import org.apache.myfaces.shared_orchestra.renderkit.RendererUtils;
    24  import org.apache.myfaces.shared_orchestra.renderkit.JSFAttr;
    25  import org.apache.myfaces.shared_orchestra.renderkit.html.HTML;
    26  import org.apache.myfaces.shared_orchestra.util.ArrayUtils;
    27  import org.apache.myfaces.shared_orchestra.util.StringUtils;
    28
    29  import javax.faces.context.FacesContext;
    30  import javax.faces.context.ResponseWriter;
    31  import javax.faces.component.UIComponent;
    32  import javax.faces.component.UIPanel;
    33  import javax.faces.component.html.HtmlPanelGrid;
    34  import java.io.IOException;
    35  import java.util.Iterator;
    36
    37  /**
    38   * @author Martin Marinschek
    39   * @version $Revision: 587938 $ $Date: 2007-10-24 12:44:21 -0500 (Wed, 24 Oct 2007) $
    40   *          <p/>
    41   *          $Log: $
    42   */
    43  public class HtmlGridRendererBase
    44          extends HtmlRenderer
    45  {
    46      private static final Log log = LogFactory.getLog(HtmlGridRendererBase.class);
    47
    48      public boolean getRendersChildren()
    49      {
    50          return true;
    51      }
    52
    53      public void encodeBegin(FacesContext facesContext, UIComponent component)
    54              throws IOException
    55      {
    56          // all work done in encodeEnd()
    57      }
    58
    59      public void encodeChildren(FacesContext context, UIComponent component)
    60          throws IOException
    61      {
    62          // all work done in encodeEnd()
    63      }
    64
    65      public void encodeEnd(FacesContext facesContext, UIComponent component)
    66              throws IOException
    67      {
    68          RendererUtils.checkParamValidity(facesContext, component, UIPanel.class);
    69
    70          int columns;
    71          if (component instanceof HtmlPanelGrid)
    72          {
    73              columns = ((HtmlPanelGrid)component).getColumns();
    74          }
    75          else
    76          {
    77              Integer i = (Integer)component.getAttributes().get(org.apache.myfaces.shared_orchestra.renderkit.JSFAttr.COLUMNS_ATTR);
    78              columns = i != null ? i.intValue() : 0;
    79          }
    80
    81          if (columns <= 0)
    82          {
    83              if (log.isErrorEnabled())
    84              {
    85                  log.error("Wrong columns attribute for PanelGrid " + component.getClientId(facesContext) + ": " + columns);
    86              }
    87              columns = 1;
    88          }
    89
    90          ResponseWriter writer = facesContext.getResponseWriter();
    91          writer.startElement(HTML.TABLE_ELEM, component);
    92          HtmlRendererUtils.writeIdIfNecessary(writer, component, facesContext);
    93          HtmlRendererUtils.renderHTMLAttributes(writer, component, HTML.TABLE_PASSTHROUGH_ATTRIBUTES);
    94
    95          writer.flush();
    96
    97          // theader and tfooter are rendered before the tbody
    98          renderHeaderOrFooter(facesContext, writer, component, columns, true);   //Header facet
    99          renderHeaderOrFooter(facesContext, writer, component, columns, false);  //Footer facet
    100
    101         renderChildren(facesContext, writer, component, columns);
    102
    103         writer.endElement(HTML.TABLE_ELEM);
    104     }
    105
    106
    107     protected void renderHeaderOrFooter(FacesContext context,
    108                                       ResponseWriter writer,
    109                                       UIComponent component,
    110                                       int columns,
    111                                       boolean header)
    112         throws IOException
    113     {
    114         UIComponent facet = component.getFacet(header ? "header" : "footer");
    115         if (facet == null) return;
    116
    117         HtmlRendererUtils.writePrettyLineSeparator(context);
    118         writer.startElement(header ? org.apache.myfaces.shared_orchestra.renderkit.html.HTML.THEAD_ELEM : HTML.TFOOT_ELEM, component);
    119         writer.startElement(HTML.TR_ELEM, component);
    120         writer.startElement(header ? HTML.TH_ELEM : HTML.TD_ELEM, component);
    121
    122         String styleClass = (component instanceof HtmlPanelGrid)
    123             ? (header ?
    124                          ((HtmlPanelGrid)component).getHeaderClass() :
    125                          ((HtmlPanelGrid)component).getFooterClass())
    126             : (header ?
    127                          (String)component.getAttributes().get(JSFAttr.HEADER_CLASS_ATTR) :
    128                          (String)component.getAttributes().get(org.apache.myfaces.shared_orchestra.renderkit.JSFAttr.FOOTER_CLASS_ATTR));
    129         if (styleClass != null)
    130         {
    131             writer.writeAttribute(HTML.CLASS_ATTR, styleClass,
    132                                   header ? JSFAttr.HEADER_CLASS_ATTR : org.apache.myfaces.shared_orchestra.renderkit.JSFAttr.FOOTER_CLASS_ATTR);
    133         }
    134
    135         if (header)
    136         {
    137             writer.writeAttribute(HTML.SCOPE_ATTR, HTML.SCOPE_COLGROUP_VALUE, null);
    138         }
    139
    140         writer.writeAttribute(HTML.COLSPAN_ATTR, Integer.toString(columns), null);
    141
    142         HtmlRendererUtils.writePrettyLineSeparator(context);
    143         RendererUtils.renderChild(context, facet);
    144
    145         HtmlRendererUtils.writePrettyLineSeparator(context);
    146         writer.endElement(header ? HTML.TH_ELEM : HTML.TD_ELEM);
    147         writer.endElement(HTML.TR_ELEM);
    148         writer.endElement(header ? HTML.THEAD_ELEM : HTML.TFOOT_ELEM);
    149     }
    150
    151     protected int childAttributes(FacesContext context,
    152             ResponseWriter writer,
    153             UIComponent component,
    154             int columnIndex)
    155         throws IOException
    156     {
    157         // subclasses can override this method to add attributes to the table cell <td> tag
    158         return columnIndex;
    159     }
    160
    161     protected void renderChildren(FacesContext context,
    162                                 ResponseWriter writer,
    163                                 UIComponent component,
    164                                 int columns)
    165         throws IOException
    166     {
    167         writer.startElement(HTML.TBODY_ELEM, component);
    168
    169         String columnClasses;
    170         String rowClasses;
    171         if (component instanceof HtmlPanelGrid)
    172         {
    173             columnClasses = ((HtmlPanelGrid)component).getColumnClasses();
    174             rowClasses =  ((HtmlPanelGrid)component).getRowClasses();
    175         }
    176         else
    177         {
    178             columnClasses = (String)component.getAttributes().get(org.apache.myfaces.shared_orchestra.renderkit.JSFAttr.COLUMN_CLASSES_ATTR);
    179             rowClasses = (String)component.getAttributes().get(JSFAttr.ROW_CLASSES_ATTR);
    180         }
    181
    182         String[] columnClassesArray = (columnClasses == null)
    183             ? ArrayUtils.EMPTY_STRING_ARRAY
    184             : StringUtils.trim(StringUtils.splitShortString(columnClasses, ','));
    185         int columnClassesCount = columnClassesArray.length;
    186
    187         String[] rowClassesArray = (rowClasses == null)
    188             ? org.apache.myfaces.shared_orchestra.util.ArrayUtils.EMPTY_STRING_ARRAY
    189             : StringUtils.trim(StringUtils.splitShortString(rowClasses, ','));
    190         int rowClassesCount = rowClassesArray.length;
    191
    192         int childCount = getChildCount(component);
    193         if (childCount > 0)
    194         {
    195             int columnIndex = 0;
    196             int rowClassIndex = 0;
    197             boolean rowStarted = false;
    198             for (Iterator it = getChildren(component).iterator(); it.hasNext(); )
    199             {
    200                 UIComponent child = (UIComponent)it.next();
    201                 if (child.isRendered())
    202                 {
    203                     if (columnIndex == 0)
    204                     {
    205                         //start of new/next row
    206                         if (rowStarted)
    207                         {
    208                             //do we have to close the last row?
    209                             writer.endElement(HTML.TR_ELEM);
    210                             HtmlRendererUtils.writePrettyLineSeparator(context);
    211                         }
    212                         writer.startElement(HTML.TR_ELEM, component);
    213                         if (rowClassIndex < rowClassesCount) {
    214                             writer.writeAttribute(HTML.CLASS_ATTR, rowClassesArray[rowClassIndex], null);
    215                         }
    216                         rowStarted = true;
    217                         rowClassIndex++;
    218                         if (rowClassIndex == rowClassesCount) {
    219                             rowClassIndex = 0;
    220                         }
    221                     }
    222
    223                     writer.startElement(HTML.TD_ELEM, component);
    224                     if (columnIndex < columnClassesCount)
    225                     {
    226                         writer.writeAttribute(HTML.CLASS_ATTR, columnClassesArray[columnIndex], null);
    227                     }
    228                     columnIndex = childAttributes(context, writer, child, columnIndex);
    229                     RendererUtils.renderChild(context, child);
    230                     writer.endElement(HTML.TD_ELEM);
    231
    232                     columnIndex++;
    233                     if (columnIndex >= columns) {
    234                         columnIndex = 0;
    235                     }
    236                 }
    237             }
    238
    239             if (rowStarted)
    240             {
    241                 if (columnIndex > 0)
    242                 {
    243                     if (log.isWarnEnabled()) log.warn("PanelGrid " + component.getClientId(context) + " has not enough children. Child count should be a multiple of the columns attribute.");
    244                     //Render empty columns, so that table is correct
    245                     for ( ; columnIndex < columns; columnIndex++)
    246                     {
    247                         writer.startElement(HTML.TD_ELEM, component);
    248                         if (columnIndex < columnClassesCount)
    249                         {
    250                             writer.writeAttribute(HTML.CLASS_ATTR, columnClassesArray[columnIndex], null);
    251                         }
    252                         writer.endElement(HTML.TD_ELEM);
    253                     }
    254                 }
    255                 writer.endElement(HTML.TR_ELEM);
    256                 HtmlRendererUtils.writePrettyLineSeparator(context);
    257             }
    258         }
    259
    260         writer.endElement(HTML.TBODY_ELEM);
    261     }
    262
    263 }