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 2008/02/17 05:06:48 UTC
svn commit: r628417 [2/3] - in /myfaces/trinidad/trunk/trinidad-sandbox:
sandbox-demo/src/main/webapp/WEB-INF/
sandbox-demo/src/main/webapp/WEB-INF/lib/ sandbox-demo/src/site/
sandbox-demo/src/test/ sandbox-impl/ sandbox-impl/src/
sandbox-impl/src/main...
Added: myfaces/trinidad/trunk/trinidad-sandbox/sandbox-impl/src/main/java/org/apache/myfaces/trinidadinternal/sandbox/renderkit/core/xhtml/TableFormLayoutRenderer.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-sandbox/sandbox-impl/src/main/java/org/apache/myfaces/trinidadinternal/sandbox/renderkit/core/xhtml/TableFormLayoutRenderer.java?rev=628417&view=auto
==============================================================================
--- myfaces/trinidad/trunk/trinidad-sandbox/sandbox-impl/src/main/java/org/apache/myfaces/trinidadinternal/sandbox/renderkit/core/xhtml/TableFormLayoutRenderer.java (added)
+++ myfaces/trinidad/trunk/trinidad-sandbox/sandbox-impl/src/main/java/org/apache/myfaces/trinidadinternal/sandbox/renderkit/core/xhtml/TableFormLayoutRenderer.java Sat Feb 16 20:06:44 2008
@@ -0,0 +1,2773 @@
+package org.apache.myfaces.trinidadinternal.sandbox.renderkit.core.xhtml;
+
+/*
+ * 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.
+ */
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIForm;
+import javax.faces.component.UIInput;
+import javax.faces.component.UINamingContainer;
+import javax.faces.context.FacesContext;
+import javax.faces.context.ResponseWriter;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.myfaces.trinidad.bean.FacesBean;
+import org.apache.myfaces.trinidad.bean.PropertyKey;
+import org.apache.myfaces.trinidad.component.UIXEditableValue;
+import org.apache.myfaces.trinidad.component.UIXGroup;
+import org.apache.myfaces.trinidad.component.UIXInput;
+import org.apache.myfaces.trinidad.component.UIXPanel;
+import org.apache.myfaces.trinidad.component.core.input.CoreInputHidden;
+import org.apache.myfaces.trinidad.sandbox.component.core.layout.CoreTableFormLayout;
+import org.apache.myfaces.trinidad.context.Agent;
+import org.apache.myfaces.trinidad.context.RenderingContext;
+import org.apache.myfaces.trinidadinternal.renderkit.core.xhtml.LabelAndMessageRenderer;
+import org.apache.myfaces.trinidadinternal.renderkit.core.xhtml.OutputUtils;
+import org.apache.myfaces.trinidadinternal.renderkit.core.xhtml.SkinSelectors;
+import org.apache.myfaces.trinidadinternal.renderkit.core.xhtml.XhtmlRenderer;
+
+public class TableFormLayoutRenderer extends XhtmlRenderer
+{
+
+ private static final Log LOG = LogFactory
+ .getLog(TableFormLayoutRenderer.class);
+
+ public static final String USED = "used";
+
+ public static final Marker FREE = new Marker("free");
+
+ public static final DecimalFormat percentFormat;
+
+ static
+ {
+ DecimalFormatSymbols symbols = new DecimalFormatSymbols();
+ symbols.setDecimalSeparator('.');
+ symbols.setGroupingSeparator(',');
+ symbols.setMinusSign('-');
+ percentFormat = new DecimalFormat("##.00", symbols);
+
+ }
+
+ /**
+ * Constructor
+ *
+ * It calls its parent constructor to define what type of keys allow (to get
+ * parameters)
+ *
+ */
+ public TableFormLayoutRenderer()
+ {
+ super(CoreTableFormLayout.TYPE);
+ }
+
+ /**
+ * This method is called to get the keys for the properties required in
+ * order to render the component.
+ *
+ */
+ @Override
+ protected void findTypeConstants(FacesBean.Type type)
+ {
+ super.findTypeConstants(type);
+
+ _rowsKey = type.findKey("rows");
+ _columnsKey = type.findKey("columns");
+ _heightKey = type.findKey("height");
+ _widthKey = type.findKey("width");
+ _inlineStyleKeyWidth = type.findKey("inlineStyle");
+ _hspaceKey = type.findKey("hspace");
+ _vspaceKey = type.findKey("vspace");
+ _percentWidthKey = type.findKey("percentWidth");
+ }
+
+ @Override
+ public boolean getRendersChildren()
+ {
+ return true;
+ }
+
+ /**
+ * This is how we can render both the user defined styleClass and our
+ * component style class.
+ */
+ @Override
+ protected void renderStyleAttributes(FacesContext context,
+ RenderingContext arc, FacesBean bean) throws IOException
+ {
+ renderStyleAttributes(context, arc, bean, AF_TABLE_FORM_STYLE_CLASS);
+ }
+
+ private String _getRows(FacesBean bean)
+ {
+ return (String) bean.getProperty(_rowsKey);
+ }
+
+ private String _getColumns(FacesBean bean)
+ {
+ return (String) bean.getProperty(_columnsKey);
+ }
+
+ /**
+ * The height is a value in pixels without px
+ * So this method return an Integer
+ *
+ * @param bean
+ * @return
+ */
+ private int _getHeight(FacesBean bean)
+ {
+ Object o = bean.getProperty(_heightKey);
+ if (o == null)
+ {
+ o = _heightKey.getDefault();
+ }
+ if (o instanceof Number)
+ return ((Number) o).intValue();
+
+ if (o instanceof String)
+ return new Integer((String) o).intValue();
+
+ return 0;
+ }
+
+ private int _getWidth(FacesBean bean)
+ {
+ Object o = bean.getProperty(_widthKey);
+
+ if (o == null)
+ {
+ o = _widthKey.getDefault();
+ }
+ if (o instanceof Number)
+ return ((Number) o).intValue();
+
+ if (o instanceof String)
+ return new Integer((String) o).intValue();
+ return 0;
+ }
+
+ private boolean _isPercentWidth(FacesBean bean)
+ {
+ Object o = bean.getProperty(_percentWidthKey);
+ if (o == null)
+ o = _percentWidthKey.getDefault();
+
+ return !Boolean.FALSE.equals(o);
+ }
+
+ private int _getHspace(FacesBean bean)
+ {
+ Object o = bean.getProperty(_hspaceKey);
+
+ if (o == null)
+ {
+ o = _hspaceKey.getDefault();
+ }
+ if (o instanceof Number)
+ return ((Number) o).intValue();
+
+ if (o instanceof String)
+ return new Integer((String) o).intValue();
+ return 0;
+ }
+
+ private int _getVspace(FacesBean bean)
+ {
+ Object o = bean.getProperty(_vspaceKey);
+
+ if (o == null)
+ {
+ o = _vspaceKey.getDefault();
+ }
+ if (o instanceof Number)
+ return ((Number) o).intValue();
+
+ if (o instanceof String)
+ return new Integer((String) o).intValue();
+ return 0;
+ }
+
+ private String _getInlineStyleWidth(FacesBean bean)
+ {
+ return (String) bean.getProperty(_inlineStyleKeyWidth);
+ }
+
+ private void _setInlineStyleWidth(FacesBean bean, String style)
+ {
+ bean.setProperty(_inlineStyleKeyWidth, style);
+ }
+
+ protected int _getColspanAddition(RenderingContext arc, int spanX)
+ {
+
+ if (spanX <= 1)
+ {
+ return 0;
+ }
+ else
+ {
+ if (Agent.AGENT_IE.equals(arc.getAgent().getAgentName()))
+ {
+ return (spanX - 1) * 6;
+ }
+ if (Agent.AGENT_GECKO.equals(arc.getAgent().getAgentName()))
+ {
+ return (spanX - 1) * 4;
+ }
+
+ }
+ return 0;
+ }
+
+ protected int _getRowspanAddition(RenderingContext arc, int spanY)
+ {
+ if (spanY <= 1)
+ {
+ return 0;
+ }
+ else
+ {
+ if (Agent.AGENT_IE.equals(arc.getAgent().getAgentName()))
+ {
+ return (spanY - 1) * 8;
+ }
+ if (Agent.AGENT_GECKO.equals(arc.getAgent().getAgentName()))
+ {
+ return (spanY - 1) * 6;
+ }
+ }
+ return 0;
+ }
+
+ /**
+ * Get how many columns has been defined
+ *
+ */
+ private int _getColumnCount(FacesBean bean)
+ {
+ String columns = this._getColumns(bean);
+ int columnCount;
+ if (columns != null)
+ {
+ columnCount = 1 + StringUtils.countMatches(columns, ";");
+ }
+ else
+ {
+ columnCount = 1;
+ }
+ return columnCount;
+ }
+
+ /**
+ * Calculate the widths of each column based on the description of width and
+ * columns attributes
+ *
+ * @return List of widths for each column
+ */
+ private String[] _getColumnWidths(FacesBean bean)
+ {
+
+ /*
+ if (this._getWidth(bean) == null)
+ {
+ return null;
+ }
+ if (this._getWidth(bean).equals(""))
+ {
+ return null;
+ }
+ */
+ String columns = this._getColumns(bean);
+
+ //Obtain an array of columns like this
+ //[1*,1*,2*,300]
+ String[] sw = StringUtils.split(columns, ';');
+ if (sw.length == 0)
+ {
+ return null;
+ }
+
+ //This array is used to return the columns widths
+ //If is in percent mode, widths looks like this:
+ //[50%,50%]
+ //If is in absolute mode it looks like this
+ //[50,50]
+ String[] widths = new String[sw.length];
+
+ double absolutePixels = 0; // Defines how many absolute space has
+ double maxRelative = 0;
+
+ for (int i = 0; i < sw.length; i++)
+ {
+ String col = sw[i];
+ if (StringUtils.contains(col, '*'))
+ {
+ String col1 = StringUtils.stripEnd(col, "*");
+ sw[i] = col1; // remove *
+ try
+ {
+ Double relative = Double.parseDouble(col1);
+ widths[i] = null;
+ maxRelative += relative;
+ }
+ catch (NumberFormatException e)
+ {
+ widths[i] = "-2";
+ }
+ }
+ else
+ {
+ // Measures in pixels, let it as is
+ widths[i] = col;
+ absolutePixels += Double.parseDouble(col);
+ }
+ }
+
+ Double cellspacing = 0d;
+
+ if (_isPercentWidth(bean))
+ {
+ //Calculate as relative width
+ //Double width = null;
+ //width = Double.parseDouble("" + this._getWidth(bean));
+ // Now calculate the widths based on
+ double actualwidth = 0;
+ double remainingspace = 100d;
+
+ if (_getHspace(bean) > 0)
+ {
+ remainingspace -= _getHspace(bean)
+ * (_getColumnCount(bean) - 1);
+ //maxRelative = remainingspace;
+ }
+
+ for (int i = 0; i < sw.length; i++)
+ {
+ String col = sw[i];
+ String col1 = widths[i];
+
+ if (col1 == null)
+ {
+ if (remainingspace > 0)
+ {
+ double value = new Double(remainingspace
+ * Double.parseDouble(col) / maxRelative);
+ widths[i] = "" + percentFormat.format(value) + "%";
+ }
+ else
+ {
+ // Nothing happens
+ widths[i] = "0";
+ }
+ }
+ else
+ {
+ // Nothing happens
+ actualwidth = actualwidth
+ + Double.parseDouble(StringUtils
+ .stripEnd(col1, "%"));
+ }
+ }
+
+ }
+ else
+ {
+ //Calculate as absolute width
+ Double width = null;
+
+ //Calculate cellspacing if available
+ //cellspacing = new Integer(this._getHspace(bean)*(this._getColumnCount(bean)-1)).doubleValue();
+ try
+ {
+ width = Double.parseDouble("" + this._getWidth(bean));
+ // Now calculate the widths based on
+ double actualwidth = cellspacing;
+ double remainingspace = width - absolutePixels
+ - (cellspacing * (sw.length + 1));
+ for (int i = 0; i < sw.length; i++)
+ {
+ String col = sw[i];
+ String col1 = widths[i];
+
+ if (col1 == null)
+ {
+ if (remainingspace > 0)
+ {
+ widths[i] = ""
+ + (new Double(remainingspace
+ * Double.parseDouble(col)
+ / maxRelative).intValue());
+ }
+ else
+ {
+ // Nothing happens
+ widths[i] = "0";
+ }
+ }
+ else
+ {
+ // Nothing happens
+ actualwidth = actualwidth + Double.parseDouble(col1)
+ + cellspacing;
+ }
+ }
+ }
+ catch (NumberFormatException e)
+ {
+ for (int i = 0; i < sw.length; i++)
+ {
+ //String col = sw[i];
+ String col1 = widths[i];
+ }
+ }
+ }
+ return widths;
+ }
+
+ /**
+ * Get how many columns has been defined
+ *
+ */
+ private int _getRowCount(FacesBean bean)
+ {
+
+ String rows = this._getRows(bean);
+ int rowCount;
+ if (rows != null)
+ {
+ rowCount = 1 + StringUtils.countMatches(rows, ";");
+ }
+ else
+ {
+ rowCount = 1;
+ }
+ return rowCount;
+ }
+
+ private String[] _getRowHeights(FacesBean bean)
+ {
+ //if (this._getHeight(bean) == null)
+ //{
+ // return null;
+ //}
+ //if (this._getHeight(bean).equals(""))
+ //{
+ // return null;
+ //}
+ if (this._getHeight(bean) <= 0)
+ {
+ return null;
+ }
+ String rows = this._getRows(bean);
+
+ String[] sw = StringUtils.split(rows, ';');
+ if (sw.length == 0)
+ {
+ return null;
+ }
+ String[] heights = new String[sw.length];
+
+ double absolutePixels = 0; // Defines how many absolute space has
+ double maxRelative = 0;
+
+ for (int i = 0; i < sw.length; i++)
+ {
+ String col = sw[i];
+ if (StringUtils.contains(col, '*'))
+ {
+ String col1 = StringUtils.stripEnd(col, "*");
+ sw[i] = col1; // remove *
+ try
+ {
+ Double relative = Double.parseDouble(col1);
+ heights[i] = null;
+ maxRelative += relative;
+ }
+ catch (NumberFormatException e)
+ {
+ heights[i] = "-2";
+ }
+ }
+ else
+ {
+ // Measures in pixels, let it as is
+ heights[i] = col;
+ absolutePixels += Double.parseDouble(col);
+ }
+ }
+
+ Double cellspacing = 0d;
+
+ Double height = null;
+ try
+ {
+ height = Double.parseDouble("" + this._getHeight(bean));
+ // Now calculate the heights based on
+ double actualheight = cellspacing;
+ double remainingspace = height - absolutePixels
+ - (cellspacing * (sw.length + 1));
+ for (int i = 0; i < sw.length; i++)
+ {
+ String col = sw[i];
+ String col1 = heights[i];
+
+ if (col1 == null)
+ {
+ if (remainingspace > 0)
+ {
+ heights[i] = ""
+ + (new Double(remainingspace
+ * Double.parseDouble(col) / maxRelative)
+ .intValue());
+ }
+ else
+ {
+ // Nothing happens
+ heights[i] = "0";
+ }
+ }
+ else
+ {
+ // Nothing happens
+ actualheight = actualheight + Double.parseDouble(col1)
+ + cellspacing;
+ }
+ }
+ }
+ catch (NumberFormatException e)
+ {
+ for (int i = 0; i < sw.length; i++)
+ {
+ //String col = sw[i];
+ String col1 = heights[i];
+ }
+ }
+ catch (NullPointerException e)
+ {
+
+ }
+ return heights;
+ }
+
+ /**
+ * Add all children component to this list.
+ *
+ * @param children
+ * @param panel
+ * @return
+ */
+ public static List<UIComponent> addChildren(List<UIComponent> children,
+ UIComponent panel)
+ {
+ for (Object o : panel.getChildren())
+ {
+ UIComponent child = (UIComponent) o;
+ if (isTransparentForLayout(child))
+ {
+ // addChildren(children, child);
+ }
+ else
+ {
+ children.add(child);
+ }
+ }
+ return children;
+ }
+
+ /**
+ *
+ * Checks if a component is transparent or not
+ *
+ * @param component
+ * @return
+ */
+ public static boolean isTransparentForLayout(UIComponent component)
+ {
+
+ // SubViewTag's component is UINamingContainer with 'null' rendererType
+ // is transparent for layouting
+
+ if (component instanceof UINamingContainer
+ && component.getRendererType() == null)
+ {
+ return true;
+ }
+ if ("facelets".equals(component.getFamily()))
+ {
+ return true;
+ }
+
+ //inputHidden is transparent too
+ if (component instanceof CoreInputHidden)
+ {
+ return true;
+ }
+
+ // also Forms are transparent for layouting
+ return component instanceof UIForm;
+ }
+
+ private boolean _isFullRow(UIComponent component)
+ {
+ String rendererType = component.getRendererType();
+
+ if (component instanceof UIXEditableValue)
+ {
+ return !_UNSUPPORTED_RENDERER_TYPES.contains(rendererType);
+ }
+
+ if (UIXPanel.COMPONENT_FAMILY.equals(component.getFamily()))
+ {
+ if ("org.apache.myfaces.trinidad.LabelAndMessage"
+ .equals(rendererType)
+ || "org.apache.myfaces.trinidad.rich.LabelAndMessage"
+ .equals(rendererType))
+ return true;
+ return false;
+ }
+ return false;
+ }
+
+ @Override
+ protected String getDefaultStyleClass(FacesBean bean)
+ {
+ return SkinSelectors.AF_LABEL_TEXT_STYLE_CLASS;
+ }
+
+ /**
+ * Do all encoding of the component
+ *
+ */
+ @SuppressWarnings("unchecked")
+ @Override
+ protected void encodeAll(FacesContext context, RenderingContext arc,
+ UIComponent component, FacesBean bean) throws IOException
+ {
+ //LOG.info("TableFormLayoutRenderer encodeAll");
+ //System.out.println("TableFormLayoutRenderer ENCODE ALL");
+ ResponseWriter rw = context.getResponseWriter();
+
+ //This panel must be encapsulated inside a div tag
+ // the root element
+ rw.startElement("div", component);
+
+ // Check if a inlineStyle has a width property, if not
+ // it append to the property the width and height in pixels
+ // to the div tag that contains the table
+ if (!StringUtils.contains(this._getInlineStyleWidth(bean), "width"))
+ {
+ if (!this._isPercentWidth(bean))
+ {
+
+ //String[] columnWidths = this._getColumnWidths(bean);
+
+ this._setInlineStyleWidth(bean,
+ (this.getInlineStyle(bean) == null ? "" : this
+ .getInlineStyle(bean))
+ + ";width: " + (this._getWidth(bean)
+ //+(this._getColumnCount(bean)*this._getHspace(bean))
+ //+(this._getColspanAddition(arc, this._getColumnCount(bean)) )
+ ) + "px");
+ }
+ else
+ {
+ this._setInlineStyleWidth(bean,
+ (this.getInlineStyle(bean) == null ? "" : this
+ .getInlineStyle(bean))
+ + ";width: " + (this._getWidth(bean)) + "%");
+ }
+ }
+ /*
+ if (!StringUtils.contains(this._getInlineStyleWidth(bean), "height")){
+ if (this._getHeight(bean) != null){
+ this._setInlineStyleWidth(bean,
+ (this.getInlineStyle(bean)==null?"":this.getInlineStyle(bean))+";height: "+
+ this._getHeight(bean)+"px");
+ }
+ }
+ */
+ renderId(context, component);
+ // When render all attributes, it render the InlineStyle
+ renderAllAttributes(context, arc, bean);
+
+ // Set the column count based on the info related on columns field
+ int maxColumns = 0;
+ maxColumns = this._getColumnCount(bean);
+
+ if (isPDA(arc))
+ {
+ maxColumns = 1;
+ }
+
+ // Set the row count based on the info related on rows field
+ int rows = 0;
+ rows = this._getRowCount(bean);
+
+ // Fetch a list of footer components:
+
+ List<UIComponent> footerComponents = null;
+ UIComponent footerFacetComponent = component.getFacet("footer");
+ if (footerFacetComponent != null)
+ {
+ if (footerFacetComponent instanceof UIXGroup)
+ {
+ // a grouping of components
+ if (footerFacetComponent.isRendered())
+ {
+ footerComponents = footerFacetComponent.getChildren();
+ }
+ }
+ else
+ {
+ // a single component
+ footerComponents = new ArrayList<UIComponent>();
+ footerComponents.add(footerFacetComponent);
+ }
+ }
+
+ _encodeChildren(context, arc, component, bean, footerComponents,
+ maxColumns, rows);
+
+ rw.endElement("div"); // the root element
+ }
+
+ @SuppressWarnings("unchecked")
+ private void _encodeChildren(FacesContext context, RenderingContext arc,
+ UIComponent component, FacesBean bean,
+ List<UIComponent> footerComponents, int maxColumns, int rows)
+ throws IOException
+ {
+ // We cannot render a nested tableForm with any more than a single
+ // column
+ // so we must monitor whether we are nested or not:
+ Map<String, Object> requestMap = context.getExternalContext()
+ .getRequestMap();
+
+ Integer nestLevelObject = (Integer) requestMap
+ .get(TABLE_FORM_NEST_LEVEL_KEY);
+ int nestLevel = 0;
+ if (nestLevelObject != null)
+ {
+ nestLevel = nestLevelObject.intValue() + 1;
+ }
+ requestMap.put(TABLE_FORM_NEST_LEVEL_KEY, nestLevel);
+
+ // Iterate through the childPeers extracting and counting the number of
+ // visible children, also count the visible children inside of visible
+ List<UIComponent> childComponents = component.getChildren();
+ //Here is adding row calculation
+ FormItemInfo visibleFormItemInfo = _extractVisibleItems(context, bean,
+ component, childComponents);
+
+ List<FormItem> visibleFormItems = visibleFormItemInfo.getFormItems();
+ //int totalFormItemCount = visibleFormItemInfo.getTotalFormItemCount();
+
+ // Iterate through the footerPeers extracting the visible children:
+ int totalFooterItemCount = 0;
+ List<FormItem> visibleFooterItems = null;
+ if (footerComponents != null)
+ {
+ FormItemInfo visibleFooterItemInfo = _extractVisibleItems(footerComponents);
+ visibleFooterItems = visibleFooterItemInfo.getFormItems();
+ totalFooterItemCount = visibleFooterItemInfo
+ .getTotalFormItemCount();
+ }
+
+ //boolean startAlignedLabels = (nestLevel == 0);
+ boolean startAlignedLabels = false;
+
+ /*
+ // Now that we have the list and counts of visible form items (and group
+ // arrangements), we must figure out how many actual columns and actual
+ // rows
+ // we really need:
+ int actualColumns = maxColumns;
+ int actualRows = rows;
+
+ if (!startAlignedLabels || (totalFormItemCount == 0)) {
+ // Must use a single column and unlimited rows:
+ actualColumns = 1;
+ actualRows = Integer.MAX_VALUE;
+ } else if (actualColumns == 1) {
+ // Developer wanted to use a single column and unlimited rows:
+ actualRows = Integer.MAX_VALUE;
+ } else {
+ // We must compute how many rows will fit in the given max number of
+ // columns
+ // and also see if there are actually fewer columns needed:
+ Dimension actualResults = TableFormLayoutRenderer
+ ._computeActualRowsAndColumns(actualRows, actualColumns,
+ totalFormItemCount, visibleFormItems);
+ actualRows = (int) actualResults.getHeight();
+ actualColumns = (int) actualResults.getWidth();
+ }
+ if (actualColumns < 1) {
+ return;
+ }
+ */
+
+ // These widths can either be pixels, percentages, or undefined.
+ // We must ensure that if using percentages or undefined that we correct
+ // them
+ // to total up properly.
+ // String labelWidth = (String) _getLabelWidth(bean);
+ // String fieldWidth = (String) _getFieldWidth(bean);
+ // Create the DOM for the form:
+ ResponseWriter rw = context.getResponseWriter();
+ rw.startElement("table", null); // the outer table
+ //OutputUtils.renderLayoutTableAttributes(context, arc, "0", null,_getWidth(bean));
+ OutputUtils.renderLayoutTableAttributes(context, arc, "0", "100%");
+
+ String footerLabelWidth = null;
+ String footerFieldWidth = null;
+
+ rw.writeAttribute("style", "width: 100%", null);
+
+ // Create the form columns:
+ /*
+ _encodeFormColumns(context, arc,
+ component, bean,
+ rw, startAlignedLabels,
+ mainLabelWidth, mainFieldWidth, actualRows, actualColumns, 1, // colSpan
+ visibleFormItems);
+ */
+ _encodeFormColumns(context, arc, component, bean, rw,
+ visibleFormItemInfo, visibleFormItems);
+
+ // Create the column-spanning footer row(s):
+ if (totalFooterItemCount > 0)
+ {
+ //LOG.info("Draw Footer components: " + totalFooterItemCount + " "
+ // + startAlignedLabels);
+ _encodeFormColumns(context, arc, component, bean, rw,
+ startAlignedLabels, footerLabelWidth, footerFieldWidth,
+ totalFooterItemCount, // row
+ // count
+ 1, // column count
+ this._getColumnCount(bean), // this is actually colSpan
+ visibleFooterItems);
+
+ }
+
+ // Indicate that we are leaving this level of nesting:
+ if (nestLevel == 0)
+ {
+ // delete the value altogether:
+ requestMap.remove(TABLE_FORM_NEST_LEVEL_KEY);
+ }
+ else
+ {
+ // decrement the value:
+ requestMap.put(TABLE_FORM_NEST_LEVEL_KEY, nestLevel - 1);
+ }
+
+ rw.endElement("tbody"); // the outer tbody
+ rw.endElement("table"); // the outer table
+ }
+
+ protected int getSpanXLabel(UIComponent component)
+ {
+ Object o = component.getAttributes().get("spanXLabel");
+ if (o == null)
+ {
+ return 1;
+ }
+ else
+ {
+ try
+ {
+ return Integer.parseInt("" + o);
+ }
+ catch (Exception e)
+ {
+ return 1;
+ }
+ }
+ }
+
+ protected int getSpanXItem(UIComponent component)
+ {
+ Object o = component.getAttributes().get("spanXItem");
+ if (o == null)
+ {
+ return 1;
+ }
+ else
+ {
+ try
+ {
+ return Integer.parseInt("" + o);
+ }
+ catch (Exception e)
+ {
+ return 1;
+ }
+ }
+ }
+
+ protected int getSpanX(UIComponent component)
+ {
+ Object o = component.getAttributes().get("spanX");
+ if (o == null)
+ {
+ return 1;
+ }
+ else
+ {
+ try
+ {
+ return Integer.parseInt("" + o);
+ }
+ catch (Exception e)
+ {
+ return 1;
+ }
+ }
+ }
+
+ protected int getSpanY(UIComponent component)
+ {
+ Object o = component.getAttributes().get("spanY");
+ if (o == null)
+ {
+ return 1;
+ }
+ else
+ {
+ try
+ {
+ return Integer.parseInt("" + o);
+ }
+ catch (Exception e)
+ {
+ return 1;
+ }
+ }
+ }
+
+ private List<Row> createRows(FacesContext context, FacesBean bean,
+ UIComponent parent)
+ {
+ List<Row> rows = new ArrayList<Row>();
+ int columnCount = this._getColumnCount(bean);
+
+ // List<UIComponent> children = addChildren(new
+ // ArrayList<UIComponent>(),
+ // getParent());
+
+ List<UIComponent> children = addChildren(new ArrayList<UIComponent>(),
+ parent);
+
+ int r = 0;
+ for (UIComponent component : children)
+ {
+
+ //Renderer renderer = context.getRenderKit().getRenderer(
+ // component.getFamily(), component.getRendererType());
+
+ //LOG.info("Component:" + component.toString());
+ //LOG.info("Family:" + component.getFamily());
+ //LOG.info("Renderer:" + component.getRendererType());
+
+ if (_isLabeledComponent(context, component))
+ {
+ //LOG.info("Component use LabelAndMessageRenderer");
+ /*
+ if ("org.apache.myfaces.trinidad.LabelAndMessage"
+ .equals(component.getRendererType())
+ || "org.apache.myfaces.trinidad.rich.LabelAndMessage"
+ .equals(component.getRendererType())){
+ */
+ //if (component instanceof UIXValue){
+ int spanXLabel = this.getSpanXLabel(component);
+ int spanXItem = this.getSpanXItem(component);
+ int spanY = this.getSpanY(component);
+
+ //try to allocate in actual row
+ int r1 = nextFreeRow(rows, r, spanXLabel + spanXItem, spanY,
+ columnCount);
+
+ if (r1 == -2)
+ {
+ //not found, add a Row and try again
+ rows.add(new Row(columnCount));
+ r = nextFreeRow(rows, r == 0 ? r : r + 1, spanXLabel
+ + spanXItem, spanY, columnCount);
+ }
+ else
+ {
+ r = r1;
+ }
+ //if (r == rows.size()) {
+ //}
+
+ int c = rows.get(r).nextFreeColumn(spanXLabel + spanXItem);
+
+ for (int i = r; i < r + spanY; i++)
+ {
+ rows.get(i)
+ .addControl(component, spanXLabel + spanXItem, c);
+ }
+
+ if (c + spanXLabel + spanXItem > columnCount)
+ {
+ //rows.get(r).fill(c + 1, c + spanXLabel + spanXItem,
+ // component.isRendered());
+ for (int i = r + 1; i < r + spanY; i++)
+ {
+
+ if (i == rows.size())
+ {
+ rows.add(new Row(columnCount));
+ }
+ rows.get(i).fill(c, c + spanXLabel + spanXItem,
+ component.isRendered());
+ }
+ }
+ else
+ {
+ //rows.get(r).fill(c + 1, c + spanXLabel + spanXItem,
+ // component.isRendered());
+ for (int i = r + 1; i < r + spanY; i++)
+ {
+
+ if (i == rows.size())
+ {
+ rows.add(new Row(columnCount));
+ }
+ rows.get(i).fill(c, c + spanXLabel + spanXItem,
+ component.isRendered());
+ }
+ }
+ }
+ else
+ {
+ //LOG.info("Component does not use LabelAndMessageRenderer");
+ int spanX = getSpanX(component);
+ int spanY = getSpanY(component);
+
+ int r1 = nextFreeRow(rows, r, spanX, spanY, columnCount);
+
+ if (r1 == -2)
+ {
+ rows.add(new Row(columnCount));
+ r = nextFreeRow(rows, r == 0 ? r : r + 1, spanX, spanY,
+ columnCount);
+ }
+ else
+ {
+ r = r1;
+ }
+
+ //if (r == rows.size()) {
+ // rows.add(new Row(columnCount));
+ //}
+ int c = rows.get(r).nextFreeColumn(spanX);
+
+ for (int i = r; i < r + spanY; i++)
+ {
+ rows.get(i).addControl(component, spanX, c);
+ }
+ //rows.get(r).fill(c + 1, c + spanX, component.isRendered());
+
+ for (int i = r + 1; i < r + spanY; i++)
+ {
+
+ if (i == rows.size())
+ {
+ rows.add(new Row(columnCount));
+ }
+ rows.get(i).fill(c, c + spanX, component.isRendered());
+ }
+ }
+ }
+ return rows;
+ }
+
+ /*
+ * Start looking from row i
+ */
+ private int nextFreeRow(List<Row> rows, int i, int spanX, int spanY,
+ int maxColumn)
+ {
+ //int i = 0;
+ for (; i < rows.size(); i++)
+ {
+ if (((Row) rows.get(i)).nextFreeColumn(spanX) != -1)
+ {
+ //create additional rows if needed
+ int curRow = i;
+ if (rows.size() > i + 1)
+ {
+ boolean success = true;
+ for (int j = i + 1; j < rows.size(); j++)
+ {
+ if (((Row) rows.get(i)).nextFreeColumn(spanX) == -1)
+ {
+ success = false;
+ break;
+ }
+ }
+ if (!success)
+ {
+ continue;
+ }
+ }
+ while (rows.size() < i + spanY)
+ {
+ rows.add(new Row(maxColumn));
+ }
+ return curRow;
+ }
+ }
+ //LOG.info("rows Avaliable: " + rows.size());
+ return -2;
+ //return i;
+ }
+
+ /**
+ * Iterates through the childPeers extracting and counting the number of
+ * visible children, also counts the visible children inside of visible
+ * UIXGroups.
+ *
+ * @param
+ */
+ @SuppressWarnings("unchecked")
+ private FormItemInfo _extractVisibleItems(List<UIComponent> children)
+ {
+ FormItemInfo formItemInfo = new FormItemInfo();
+ int totalFormItemCount = 0;
+ for (UIComponent child : children)
+ {
+ /*
+ * Object spanXItem =
+ * (Object)child.getAttributes().get("spanXItem"); if (spanXItem !=
+ * null){ LOG.debug("spanXItem:"+spanXItem); }
+ */
+ if (child.isRendered())
+ {
+ if (child instanceof UIXGroup)
+ {
+ // only count children of the group
+ List<UIComponent> groupChildren = child.getChildren();
+ int visibleChildrenCount = 0;
+ for (UIComponent groupChild : groupChildren)
+ {
+ if (groupChild.isRendered())
+ {
+ // count the group child
+ visibleChildrenCount++;
+ }
+ }
+ if (visibleChildrenCount > 0)
+ {
+ totalFormItemCount += visibleChildrenCount;
+ formItemInfo.add(child, visibleChildrenCount, true);
+ }
+ }
+ else
+ {
+ // only count the child
+ totalFormItemCount++;
+ formItemInfo.add(child, 1, false);
+ }
+ }
+ }
+ formItemInfo.setTotalFormItemCount(totalFormItemCount);
+
+ return formItemInfo;
+ }
+
+ /**
+ * Iterates through the childPeers extracting and counting the number of
+ * visible children, also counts the visible children inside of visible
+ * UIXGroups.
+ *
+ * @param
+ */
+ @SuppressWarnings("unchecked")
+ private FormItemInfo _extractVisibleItems(FacesContext context,
+ FacesBean bean, UIComponent parent, List<UIComponent> children)
+ {
+ FormItemInfo formItemInfo = new FormItemInfo();
+ int totalFormItemCount = 0;
+ for (UIComponent child : children)
+ {
+ /*
+ * Object spanXItem =
+ * (Object)child.getAttributes().get("spanXItem"); if (spanXItem !=
+ * null){ LOG.debug("spanXItem:"+spanXItem); }
+ */
+ if (child.isRendered())
+ {
+ if (child instanceof UIXGroup)
+ {
+ // only count children of the group
+ List<UIComponent> groupChildren = child.getChildren();
+ int visibleChildrenCount = 0;
+ for (UIComponent groupChild : groupChildren)
+ {
+ if (groupChild.isRendered())
+ {
+ // count the group child
+ visibleChildrenCount++;
+ }
+ }
+ if (visibleChildrenCount > 0)
+ {
+ totalFormItemCount += visibleChildrenCount;
+ formItemInfo.add(child, visibleChildrenCount, true);
+ }
+ }
+ else
+ {
+ // only count the child
+ totalFormItemCount++;
+ formItemInfo.add(child, 1, false);
+ }
+ }
+ }
+ formItemInfo.setTotalFormItemCount(totalFormItemCount);
+
+ formItemInfo.setLayoutRows(this.createRows(context, bean, parent));
+
+ return formItemInfo;
+ }
+
+ private boolean isLabelAndMessageRenderer(UIComponent cell)
+ {
+ return false;
+ }
+
+ /**
+ * Encode the header columns for this component,
+ * using colgroup and then thead tags to ensure proper
+ * definition and behaviour
+ *
+ * @param context
+ * @param arc
+ * @param component
+ * @param bean
+ * @param rw
+ * @throws IOException
+ */
+ private void _encodeFormColumnsBase(FacesContext context,
+ RenderingContext arc, UIComponent component, FacesBean bean,
+ ResponseWriter rw, String[] columnWidths) throws IOException
+ {
+
+ // START COLUMN DEFINE
+
+ if (columnWidths != null)
+ {
+ rw.startElement("colgroup", null);
+ for (int i = 0; i < columnWidths.length; i++)
+ {
+ if (columnWidths[i] != null)
+ {
+ if (_isPercentWidth(bean))
+ {
+ int cellWidth = ((Double) Double
+ .parseDouble(StringUtils.stripEnd(
+ columnWidths[i], "%"))).intValue();
+ if (cellWidth != -2)
+ {
+ // cellWidth += getCellPadding(context, component,
+ // i);
+ rw.startElement("col", null);
+ rw.writeAttribute("width", columnWidths[i], null);
+ rw.endElement("col");
+ }
+ }
+ else
+ {
+ int cellWidth = ((Integer) Integer
+ .parseInt(columnWidths[i])).intValue();
+ if (cellWidth != -2)
+ {
+ // cellWidth += getCellPadding(context, component,
+ // i);
+ rw.startElement("col", null);
+ rw.writeAttribute("width", Integer
+ .toString(cellWidth), null);
+ rw.endElement("col");
+ }
+ }
+ if (_getHspace(bean) > 0 && i + 1 < columnWidths.length)
+ {
+ rw.startElement("col", null);
+ rw.writeAttribute("width", _getHspace(bean)
+ + (_isPercentWidth(bean) ? "%" : ""), null);
+ rw.endElement("col");
+ }
+ }
+
+ }
+ rw.endElement("colgroup");
+ }
+
+ rw.startElement("thead", null);
+ rw.startElement("tr", null);
+ if (columnWidths != null)
+ {
+ for (int i = 0; i < columnWidths.length; i++)
+ {
+
+ if (columnWidths[i] != null)
+ {
+ if (_isPercentWidth(bean))
+ {
+ int cellWidth = ((Double) Double
+ .parseDouble(StringUtils.stripEnd(
+ columnWidths[i], "%"))).intValue();
+ if (cellWidth != -2)
+ {
+ rw.startElement("td", null);
+ renderStyleClass(context, arc,
+ AF_TABLE_FORM_COLUMN_STYLE_CLASS);
+
+ rw.writeAttribute("width", columnWidths[i], null);
+ rw.endElement("td");
+ }
+ }
+ else
+ {
+ int cellWidth = ((Integer) Integer
+ .parseInt(columnWidths[i])).intValue();
+ if (cellWidth != -2)
+ {
+ // cellWidth += getCellPadding(context, component,
+ // i);
+ rw.startElement("td", null);
+ rw.writeAttribute("width", Integer
+ .toString(cellWidth), null);
+ rw.endElement("td");
+ }
+ }
+ }
+ if (_getHspace(bean) > 0 && i + 1 < columnWidths.length)
+ {
+ rw.startElement("td", null);
+ rw.writeAttribute("width", _getHspace(bean)
+ + (_isPercentWidth(bean) ? "%" : ""), null);
+ rw.endElement("td");
+ }
+ }
+ }
+ rw.endElement("tr");
+ rw.endElement("thead");
+ // END COLUMN DEFINE
+ }
+
+ private boolean _isLabeledComponent(FacesContext context, UIComponent cell)
+ {
+ if (LabelAndMessageRenderer.class.isAssignableFrom(context
+ .getRenderKit().getRenderer(cell.getFamily(),
+ cell.getRendererType()).getClass()))
+ {
+ return true;
+ }
+ return false;
+ }
+
+ @SuppressWarnings("unchecked")
+ private void _encodeFormColumns(FacesContext context, RenderingContext arc,
+ UIComponent component, FacesBean bean, ResponseWriter rw,
+ FormItemInfo visibleFormItemInfo, List<FormItem> visibleItems)
+ throws IOException
+ {
+
+ if (visibleItems.isEmpty())
+ return;
+
+ //Get the column widths to be rendered in the component
+ String[] columnWidths = this._getColumnWidths(bean);
+
+ _encodeFormColumnsBase(context, arc, component, bean, rw, columnWidths);
+
+ rw.startElement("tbody", null); // the outer tbody
+
+ //START ROW DEFINE
+ List<Row> rows = visibleFormItemInfo.getLayoutRows();
+
+ String[] rowHeights = this._getRowHeights(bean);
+
+ for (int rowIndex = 0; rowIndex < rows.size(); rowIndex++)
+ {
+ Row row = rows.get(rowIndex);
+
+ if (!row.isHidden())
+ {
+ rw.startElement("tr", null);
+
+ if (rowHeights != null)
+ {
+ //rw.writeAttribute("height", rowHeights[rowIndex], null); //Deprecated attribute
+ rw.writeAttribute("style",
+ "height:" + rowHeights[rowIndex], null); //Better this
+ }
+
+ List cells = row.getElements();
+
+ int numColumn = 0; // This is for count the actual column for
+ // set the width of the cell
+ boolean firstPut = false;
+
+ LOG.info("ROW:" + rowIndex);
+
+ int usedcells = 0;
+ int componentcells = 0;
+
+ for (int columnIndex = 0; columnIndex < cells.size(); columnIndex++)
+ {
+ Object object = cells.get(columnIndex);
+
+ if (object.toString().equals(TableFormLayoutRenderer.USED))
+ {
+ LOG.info("USED");
+ usedcells++;
+ continue; // ignore the markers UIGridLayout.Used
+ }
+ if (object.equals(TableFormLayoutRenderer.FREE))
+ {
+ LOG.info("FREE");
+ continue;
+ }
+ UIComponent cell = (UIComponent) object;
+
+ LOG.info("COMPONENT: " + usedcells + " " + componentcells);
+
+ if (usedcells > componentcells)
+ {
+ LOG.info("ADD Additional td: ");
+ componentcells = usedcells;
+ rw.startElement("td", null);
+ if (this._isPercentWidth(bean))
+ {
+ rw.writeAttribute("width", this._getHspace(bean)
+ + "%", null);
+ }
+ else
+ {
+ rw.writeAttribute("width", this._getHspace(bean),
+ null);
+ }
+ rw.endElement("td");
+ }
+
+ usedcells++;
+
+ int spanX = 1;
+ int spanY = 1;
+
+ //If this is a labeled component try to get
+ //attributes that define its behaviour
+ //like spanX and spanY
+ if (_isLabeledComponent(context, cell))
+ {
+ spanX = this.getSpanXLabel(cell)
+ + this.getSpanXItem(cell);
+ spanY = this.getSpanY(cell);
+ }
+ else
+ {
+ spanX = this.getSpanX(cell);
+ spanY = this.getSpanY(cell);
+ }
+
+ componentcells += spanX;
+
+ if (!cell.isRendered())
+ {
+ continue;
+ }
+
+ if (this._getHspace(bean) > 0)
+ {
+ if (firstPut)
+ {
+ LOG.info("Normal td: ");
+ rw.startElement("td", null);
+ if (this._isPercentWidth(bean))
+ {
+ rw.writeAttribute("width", this
+ ._getHspace(bean)
+ + "%", null);
+ }
+ else
+ {
+ rw.writeAttribute("width", this
+ ._getHspace(bean), null);
+ }
+ rw.endElement("td");
+ }
+ }
+
+ firstPut = true;
+
+ String cw = this.calculateSize(bean, columnWidths,
+ numColumn, spanX);
+
+ if (columnWidths != null)
+ {
+ numColumn += spanX;
+ }
+
+ String ch = this.calculateRowSize(bean, rowHeights,
+ rowIndex, spanY);
+
+ rw.startElement("td", null);
+ if (this._getHspace(bean) > 0)
+ {
+ rw.writeAttribute("colspan", spanX + spanX - 1, null);
+ }
+ else
+ {
+ rw.writeAttribute("colspan", spanX, null);
+ }
+ if (this._getVspace(bean) > 0)
+ {
+ rw.writeAttribute("rowspan", spanY + spanY - 1, null);
+ }
+ else
+ {
+ rw.writeAttribute("rowspan", spanY, null);
+ }
+
+ if (!_isPercentWidth(bean)
+ && !_isLabeledComponent(context, cell))
+ {
+ rw.writeAttribute("width", Integer.parseInt(this
+ .calculateSize(bean, columnWidths, numColumn
+ - spanX, this.getSpanX(cell)))
+ //+ _getColspanAddition(arc, spanX)
+ + ((this.getSpanX(cell) - 1) * this
+ ._getHspace(bean)), null);
+ }
+
+ if (Agent.AGENT_IE.equals(arc.getAgent().getAgentName())
+ && _isPercentWidth(bean))
+ {
+ //This code avoid bad column width when using percent
+ //on IE
+ rw.startElement("table", cell);
+ if (_isPercentWidth(bean))
+ {
+ OutputUtils.renderLayoutTableAttributes(context,
+ arc, "0", "0", "100%");
+ }
+ else
+ {
+ OutputUtils.renderLayoutTableAttributes(context,
+ arc, "0", "0", cw);
+ }
+ rw.startElement("tr", null);
+ rw.startElement("td", cell);
+ rw.startElement("div", cell);
+
+ }
+
+ // The trick for do the illusion of separate label and context
+ //cell is to create a table surrounding the component. In this way
+ //we do not modify the behavior of LabelAndMessageRenderer!.
+
+ rw.startElement("table", null); // inner table
+
+ //If this is a labeled component we have to create proper
+ //colgroup tags to define column widths.
+ //Here is the big trick.
+ //If the component is not labeled, we don't have to do anything.
+ if (_isLabeledComponent(context, cell))
+ {
+ OutputUtils.renderLayoutTableAttributes(context, arc,
+ "0", "0", "100%");
+ if (_isPercentWidth(bean))
+ {
+
+ String labelWidth = this.calculateSize(bean,
+ columnWidths, numColumn - spanX, this
+ .getSpanXLabel(cell));
+ String fieldWidth = this.calculateSize(bean,
+ columnWidths, numColumn
+ - this.getSpanXItem(cell), this
+ .getSpanXItem(cell));
+
+ //This is a strange part. the label and the field should be adjusted
+ //0.5 to avoid alineation errors. When there are too many colspan
+ //we need also a adjust
+ //labelWidth = "" +(Double.parseDouble(StringUtils.stripEnd(labelWidth,
+ // "%"))-0.5d
+ // -( new Double((spanX-2)) * 0.27d )
+ // )+"%";
+ //fieldWidth = ""+(Double.parseDouble(StringUtils.stripEnd(fieldWidth,
+ // "%"))+0.5d
+ // +( new Double((spanX-2)) * 0.27d )
+ // )+"%";
+
+ double maxPercentWidth = Double
+ .parseDouble(StringUtils.stripEnd(
+ labelWidth, "%"))
+ + _getHspace(bean)
+ + Double.parseDouble(StringUtils.stripEnd(
+ fieldWidth, "%"));
+
+ rw.startElement("colgroup", null);
+ rw.startElement("col", null);
+ rw
+ .writeAttribute(
+ "width",
+ (Double.parseDouble(StringUtils
+ .stripEnd(labelWidth, "%")) * 100 / maxPercentWidth)
+ + "%", null);
+ rw.endElement("col");
+
+ if (_getHspace(bean) > 0)
+ {
+ rw.startElement("col", null);
+ rw
+ .writeAttribute(
+ "width",
+ (_getHspace(bean) * 100 / maxPercentWidth)
+ + "%", null);
+ rw.endElement("col");
+ }
+
+ rw.startElement("col", null);
+ rw
+ .writeAttribute(
+ "width",
+ (Double.parseDouble(StringUtils
+ .stripEnd(fieldWidth, "%")) * 100 / maxPercentWidth)
+ + "%", null);
+ rw.endElement("col");
+ rw.endElement("colgroup");
+
+ rw.startElement("thead", null);
+ rw.startElement("tr", null);
+ rw.startElement("td", null);
+ rw
+ .writeAttribute(
+ "width",
+ (Double.parseDouble(StringUtils
+ .stripEnd(labelWidth, "%")) * 100 / maxPercentWidth)
+ + "%", null);
+ rw.endElement("td");
+
+ if (_getHspace(bean) > 0)
+ {
+ rw.startElement("td", null);
+ rw
+ .writeAttribute(
+ "width",
+ (_getHspace(bean) * 100 / maxPercentWidth)
+ + "%", null);
+ rw.endElement("td");
+ }
+
+ rw.startElement("td", null);
+ rw
+ .writeAttribute(
+ "width",
+ (Double.parseDouble(StringUtils
+ .stripEnd(fieldWidth, "%")) * 100 / maxPercentWidth)
+ + "%", null);
+ rw.endElement("td");
+ rw.endElement("tr");
+ rw.endElement("thead");
+ }
+ else
+ {
+ rw.startElement("colgroup", null);
+
+ rw.startElement("col", null);
+ rw
+ .writeAttribute(
+ "width",
+ Integer
+ .parseInt(this
+ .calculateSize(
+ bean,
+ columnWidths,
+ numColumn
+ - spanX,
+ this
+ .getSpanXLabel(cell)))
+ + ((getSpanXLabel(cell) - 1) * _getHspace(bean))
+ //+_getColspanLabelAddition(arc, getSpanXLabel(cell))
+
+ , null);
+ rw.endElement("col");
+
+ if (_getHspace(bean) > 0)
+ {
+ rw.startElement("col", null);
+ rw.writeAttribute("width", _getHspace(bean),
+ null);
+ rw.endElement("col");
+ }
+
+ rw.startElement("col", null);
+ rw
+ .writeAttribute(
+ "width",
+ Integer
+ .parseInt(this
+ .calculateSize(
+ bean,
+ columnWidths,
+ numColumn
+ - this
+ .getSpanXItem(cell),
+ this
+ .getSpanXItem(cell)))
+ + ((getSpanXItem(cell) - 1) * _getHspace(bean))
+ //+_getColspanAddition(arc, this.getSpanXItem(cell))
+ //+_getColspanFieldAddition(arc,this.getSpanXItem(cell))
+ , null);
+ rw.endElement("col");
+ rw.endElement("colgroup");
+
+ rw.startElement("thead", null);
+ rw.startElement("tr", null);
+
+ rw.startElement("td", null);
+ rw
+ .writeAttribute(
+ "width",
+ Integer
+ .parseInt(this
+ .calculateSize(
+ bean,
+ columnWidths,
+ numColumn
+ - spanX,
+ this
+ .getSpanXLabel(cell)))
+ + ((getSpanXLabel(cell) - 1) * _getHspace(bean))
+ //+_getColspanLabelAddition(arc, getSpanXLabel(cell))
+ , null);
+ rw.endElement("td");
+
+ if (_getHspace(bean) > 0)
+ {
+ rw.startElement("td", null);
+ rw.writeAttribute("width", _getHspace(bean),
+ null);
+ rw.endElement("td");
+ }
+
+ rw.startElement("td", null);
+ rw
+ .writeAttribute(
+ "width",
+ Integer
+ .parseInt(this
+ .calculateSize(
+ bean,
+ columnWidths,
+ numColumn
+ - this
+ .getSpanXItem(cell),
+ this
+ .getSpanXItem(cell)))
+ + ((getSpanXItem(cell) - 1) * _getHspace(bean))
+ //+_getColspanAddition(arc, this.getSpanXItem(cell))
+ //+_getColspanFieldAddition(arc, this.getSpanXItem(cell))
+ , null);
+ rw.endElement("td");
+ rw.endElement("tr");
+ rw.endElement("thead");
+ }
+ }
+ else
+ {
+ if (_isPercentWidth(bean))
+ {
+ OutputUtils.renderLayoutTableAttributes(context,
+ arc, "0", "0", "100%");
+ }
+ else
+ {
+ OutputUtils.renderLayoutTableAttributes(context,
+ arc, "0", "0", Integer.parseInt(this
+ .calculateSize(bean, columnWidths,
+ numColumn - spanX, this
+ .getSpanX(cell)))
+ //+ _getColspanAddition(arc, spanX)
+ + ((this.getSpanX(cell) - 1) * this
+ ._getHspace(bean)));
+ }
+ }
+
+ rw.startElement("tbody", null); // inner tbody
+
+ String rowHeight = this.calculateRowSize(bean, rowHeights,
+ rowIndex, spanY);
+
+ rw.startElement("tr", null); // label row
+
+ if (!rowHeight.equals("0"))
+ {
+
+ if (this._getVspace(bean) > 0)
+ {
+ rowHeight = ""
+ + (Integer.parseInt(rowHeight) + (this
+ ._getVspace(bean) * (this
+ .getSpanY(cell) - 1)));
+ }
+
+ if (this._getHeight(bean) > 0 && spanY > 1)
+ {
+ rowHeight = ""
+ + (Integer.parseInt(rowHeight) + this
+ ._getRowspanAddition(arc, spanY));
+ }
+
+ //rw.writeAttribute("height", rowHeight, null); //Deprecated attribute
+ rw.writeAttribute("style",
+ "height:" + rowHeight + "px", null); //Better this
+ }
+
+ //now we have to set the style attribute with proper height and width
+ //and render the children!.
+ if (_isLabeledComponent(context, cell))
+ {
+ FacesBean cbean = getFacesBean(cell);
+
+ FacesBean.Type ctype = cbean.getType();
+
+ //// DEFINE CONTENT STYLE FOR THE COMPONENT
+
+ PropertyKey _contentStyle = ctype
+ .findKey("contentStyle");
+
+ String contentStyle = (String) cbean
+ .getProperty(_contentStyle);
+
+ if (!StringUtils.contains(contentStyle, "height"))
+ {
+ if (!rowHeight.equals("0"))
+ {
+ cbean.setProperty(_contentStyle,
+ (contentStyle == null ? ""
+ : contentStyle)
+ + ";height: "
+ + rowHeight
+ + "px");
+ }
+ }
+
+ contentStyle = (String) cbean
+ .getProperty(_contentStyle);
+
+ if (!StringUtils.contains(contentStyle, "width"))
+ {
+ if (_isPercentWidth(bean))
+ {
+ cbean.setProperty(_contentStyle,
+ (contentStyle == null ? ""
+ : contentStyle)
+ + ";width: 100%");
+ }
+ else
+ {
+ Integer colWidth = Integer
+ .parseInt(this
+ .calculateSize(
+ bean,
+ columnWidths,
+ numColumn
+ - this
+ .getSpanXItem(cell),
+ this.getSpanXItem(cell)))
+ + _getCorrectWidthInputComponent(arc,
+ cell)
+ + ((getSpanXItem(cell) - 1) * _getHspace(bean))
+ //+_getColspanAddition(arc, this.getSpanXItem(cell))
+ //+_getColspanFieldAddition(arc, this.getSpanXItem(cell))
+ ;
+ //- (this.getSpanXItem(cell) == 1 ? this
+ // ._getCellspacing(bean) : 0) - 3;
+
+ cbean.setProperty(_contentStyle,
+ (contentStyle == null ? ""
+ : contentStyle)
+ + ";width:" + colWidth + "px"); // + colWidth + "px" //100%
+ }
+ }
+
+ //Set the SkinResourceKeyMap form encode this
+ //component
+ arc
+ .setSkinResourceKeyMap(TableFormLayoutRenderer._RESOURCE_KEY_SIDE_BY_SIDE_MAP);
+
+ Map<String, Object> requestMap = context
+ .getExternalContext().getRequestMap();
+
+ Integer hspaceObject = (Integer) requestMap
+ .get(TABLE_FORM_HSPACE);
+
+ Boolean percentWidthObject = (Boolean) requestMap
+ .get(TABLE_FORM_PERCENTWIDTH);
+
+ if (_getHspace(bean) > 0)
+ {
+ requestMap.put(TABLE_FORM_HSPACE, _getHspace(bean));
+ requestMap.put(TABLE_FORM_PERCENTWIDTH,
+ _isPercentWidth(bean));
+ }
+
+ _encodeFormItem2(context, arc, rw, false, cell);
+
+ if (hspaceObject == null)
+ {
+ requestMap.remove(TABLE_FORM_HSPACE);
+ }
+ else
+ {
+ requestMap.put(TABLE_FORM_HSPACE, hspaceObject
+ .intValue());
+ }
+
+ if (percentWidthObject == null)
+ {
+ requestMap.remove(TABLE_FORM_PERCENTWIDTH);
+ }
+ else
+ {
+ requestMap.put(TABLE_FORM_PERCENTWIDTH,
+ percentWidthObject.booleanValue());
+ }
+
+ }
+ else
+ {
+ rw.startElement("td", null);
+
+ if (!_isPercentWidth(bean))
+ {
+ rw.writeAttribute("width", Integer.parseInt(this
+ .calculateSize(bean, columnWidths,
+ numColumn - spanX, this
+ .getSpanX(cell)))
+ + _getColspanAddition(arc, spanX)
+ + ((this.getSpanX(cell) - 1) * this
+ ._getHspace(bean)), null);
+ }
+
+ renderStyleClass(context, arc,
+ AF_TABLE_FORM_CONTENT_CELL_STYLE_CLASS);
+
+ String style = (String) cell.getAttributes().get(
+ "style");
+ if (style == null)
+ {
+ style = "";
+ }
+ if (_isPercentWidth(bean))
+ {
+ if (style != null
+ && !StringUtils.contains(style, "width"))
+ {
+ cell.getAttributes().put("style",
+ style + ";width:100%");
+ }
+ }
+ else
+ {
+ if (style != null
+ && !StringUtils.contains(style, "width"))
+ {
+
+ cell
+ .getAttributes()
+ .put(
+ "style",
+ style
+ + ";width:"
+ + (Integer
+ .parseInt(this
+ .calculateSize(
+ bean,
+ columnWidths,
+ numColumn
+ - spanX,
+ this
+ .getSpanX(cell)))
+ //+ _getColspanAddition(arc, spanX)
+ + ((this
+ .getSpanX(cell) - 1) * this
+ ._getHspace(bean)) + _getCorrectWidthInputComponent(
+ arc, cell))
+ + "px");
+ }
+ }
+
+ _encodeFormItem2(context, arc, rw, false, cell);
+ rw.endElement("td");
+ }
+
+ rw.endElement("tr"); // field row
+ rw.endElement("tbody"); // inner tbody
+ rw.endElement("table"); // inner table
+
+ if (Agent.AGENT_IE.equals(arc.getAgent().getAgentName())
+ && _isPercentWidth(bean))
+ {
+ //This code avoid bad column width when using percent
+ //on IE
+ rw.endElement("div");
+ rw.endElement("td");
+ rw.endElement("tr");
+ rw.endElement("table");
+ }
+
+ rw.endElement("td");
+
+ }
+ rw.endElement("tr");
+ }
+
+ //Now we need tr if vspace is > 0
+
+ if (this._getVspace(bean) > 0)
+ {
+ if (rowIndex + 1 < rows.size())
+ {
+ rw.startElement("tr", null);
+ rw.writeAttribute("style", "height:"
+ + this._getVspace(bean) + "px", null);
+ rw.endElement("tr");
+ }
+ }
+ }
+ }
+
+ protected int _getCorrectWidthInputComponent(RenderingContext arc,
+ UIComponent cell)
+ {
+
+ if (UIInput.class.isAssignableFrom(cell.getClass())
+ || UIXInput.class.isAssignableFrom(cell.getClass()))
+ {
+ if (Agent.AGENT_IE.equals(arc.getAgent().getAgentName()))
+ {
+ return -6;
+ }
+ if (Agent.AGENT_GECKO.equals(arc.getAgent().getAgentName()))
+ {
+ return -4;
+ }
+ }
+ return 0;
+ }
+
+ protected String calculateSize(FacesBean bean, String[] sizes, int num,
+ int span)
+ {
+ String cw = "0";
+ if (sizes != null)
+ {
+ //LOG.debug("calculateSize:" + sizes.toString() + " " + num + " "
+ // + span);
+ if (span == 1)
+ {
+ cw = sizes[num];
+ //numColumn++;
+ }
+ else
+ {
+ if (_isPercentWidth(bean))
+ {
+ double cw1 = 0;
+ for (int i = num; i < num + span; i++)
+ {
+ cw1 += Double.parseDouble(StringUtils.stripEnd(
+ sizes[i], "%"));
+ }
+ //cw1 = cw1 + this._getCellspacing(bean) * (span - 1);
+ cw = "" + cw1;
+ }
+ else
+ {
+ int cw1 = 0;
+ for (int i = num; i < num + span; i++)
+ {
+ cw1 += Integer.parseInt(sizes[i]);
+ }
+ //cw1 = cw1;// + this._getCellspacing(bean) * (span - 1);
+ cw = "" + cw1;
+ }
+ }
+ }
+ return cw;
+ }
+
+ protected String calculateRowSize(FacesBean bean, String[] sizes, int num,
+ int span)
+ {
+ String cw = "0";
+ if (sizes != null)
+ {
+ //LOG.debug("calculateSize:" + sizes.toString() + " " + num + " "
+ // + span);
+ if (span == 1)
+ {
+ cw = sizes[num];
+ //numColumn++;
+ }
+ else
+ {
+ int cw1 = 0;
+ for (int i = num; i < num + span; i++)
+ {
+ cw1 += Integer.parseInt(sizes[i]);
+ }
+ //cw1 = cw1;// + this._getCellspacing(bean) * (span - 1);
+ cw = "" + cw1;
+ }
+ }
+ return cw;
+ }
+
+ @SuppressWarnings("unchecked")
+ private void _encodeFormColumns(FacesContext context, RenderingContext arc,
+ UIComponent component, FacesBean bean, ResponseWriter rw,
+ boolean startAlignedLabels, String effectiveLabelWidth,
+ String effectiveFieldWidth, int actualRows, int actualColumns,
+ int colSpan, List<FormItem> visibleItems) throws IOException
+ {
+
+ if (visibleItems.isEmpty())
+ return;
+
+ rw.startElement("tr", null); // the outer row
+ int currentItemIndex = 0;
+ int visibleItemsLength = visibleItems.size();
+ String outerColumnWidth = Math.floor(((double) 100) / actualColumns)
+ + "%";
+ for (int col = 0; col < actualColumns; col++)
+ {
+ rw.startElement("td", null); // the outer column
+ renderStyleClass(context, arc, AF_TABLE_FORM_COLUMN_STYLE_CLASS);
+ rw.writeAttribute("colspan", colSpan, null);
+ if (col < actualColumns - 1) // let the last column take the leftover space
+ {
+ rw.writeAttribute("width", outerColumnWidth, null);
+ }
+
+ rw.startElement("table", null); // the inner table
+ OutputUtils.renderLayoutTableAttributes(context, arc, "0", "100%");
+ rw.startElement("tbody", null); // the inner tbody
+ if (startAlignedLabels)
+ {
+ rw.startElement("tr", null); // the sizing row
+ rw.startElement("td", null); // the sizing label cell
+ if (effectiveLabelWidth != null)
+ {
+ rw.writeAttribute("style", "width: " + effectiveLabelWidth,
+ null);
+ }
+ rw.endElement("td"); // the sizing label cell
+ rw.startElement("td", null); // the sizing field cell
+ if (effectiveFieldWidth != null)
+ {
+ rw.writeAttribute("style", "width: " + effectiveFieldWidth,
+ null);
+ }
+ rw.endElement("td"); // the sizing field cell
+ rw.endElement("tr"); // the sizing row
+ }
+ int currentRow = 0;
+ boolean groupSeparatorNeeded = false;
+ while (currentRow < actualRows)
+ {
+ FormItem item = visibleItems.get(currentItemIndex);
+ UIComponent itemChild = item.getChild();
+ int itemSize = item.getSize();
+ boolean isGroup = item.isGroup();
+ int sizeAfterThis = currentRow + itemSize;
+ if ((currentRow == 0) || (sizeAfterThis <= actualRows))
+ {
+ if (isGroup)
+ {
+ if (currentRow > 0)
+ {
+ // insert group separator
+ TableFormLayoutRenderer._encodeGroupDivider(
+ context, arc, rw, startAlignedLabels);
+ }
+ groupSeparatorNeeded = true;
+ List<UIComponent> groupChildren = itemChild
+ .getChildren();
+ for (UIComponent groupChild : groupChildren)
+ {
+ if (groupChild.isRendered())
+ {
+ // add the group child
+ _encodeFormItem(context, arc, rw,
+ startAlignedLabels, groupChild);
+ }
+ }
+ }
+ else
+ {
+ if (groupSeparatorNeeded)
+ {
+ groupSeparatorNeeded = false;
+ // insert group separator
+ TableFormLayoutRenderer._encodeGroupDivider(
+ context, arc, rw, startAlignedLabels);
+ }
+ _encodeFormItem(context, arc, rw, startAlignedLabels,
+ itemChild);
+ }
+
+ // This particular item or group of items fits:
+ currentItemIndex++;
+ currentRow += itemSize;
+
+ if (currentItemIndex >= visibleItemsLength)
+ {
+ // there are no more items
+ break;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+ rw.endElement("tbody"); // the inner tbody
+ rw.endElement("table"); // the inner table
+ rw.endElement("td"); // the outer column
+ }
+ rw.endElement("tr"); // the outer row
+ }
+
+ private static void _encodeGroupDivider(FacesContext context,
+ RenderingContext arc, ResponseWriter rw, boolean startAlignedLabels)
+ throws IOException
+ {
+ rw.startElement("tr", null);
+ rw.startElement("td", null);
+ if (startAlignedLabels)
+ {
+ rw.writeAttribute("colspan", "2", null);
+ }
+ // =-= mcc I considered using an HR but IE6 always adds its own border
+ // around
+ // any background graphics you attempt to put inside. Firefox 1.5
+ // behaves
+ // as expected. Using a DIV until we know a way to fix IE6.
+ rw.startElement("div", null);
+ renderStyleClass(context, arc, AF_TABLE_FORM_SEPARATOR_STYLE_CLASS);
+ rw.endElement("div");
+ rw.endElement("td");
+ rw.endElement("tr");
+ }
+
+ private void _encodeFormItem(FacesContext context, RenderingContext arc,
+ ResponseWriter rw, boolean startAlignedLabels, UIComponent item)
+ throws IOException
+ {
+ boolean isFullRow = _isFullRow(item);
+ if (isFullRow) // "plays well" with panelForm
+ {
+ // If a peer wants to play well with panelForm, it must use the proper
+ // PanelForm wrapper APIs to ensure proper DOM structure.
+ _encodeBeforeLabelTd(context, arc, rw, startAlignedLabels);
+ Map<String, String> originalResourceKeyMap = arc
+ .getSkinResourceKeyMap();
+ try
+ {
+ if (startAlignedLabels)
+ {
+ arc
+ .setSkinResourceKeyMap(TableFormLayoutRenderer._RESOURCE_KEY_SIDE_BY_SIDE_MAP);
+ }
+ else
+ {
+ arc
+ .setSkinResourceKeyMap(TableFormLayoutRenderer._RESOURCE_KEY_STACKED_MAP);
+ }
+ encodeChild(context, item);
+ }
+ finally
+ {
+ arc.setSkinResourceKeyMap(originalResourceKeyMap);
+ }
+ _encodeAfterFieldTd(rw, startAlignedLabels);
+ }
+ else
+ // does not "play well" with panelForm
+ {
[... 442 lines stripped ...]