Index: component-metadata/src/main/resources/conf/ice_cust_properties/cust-panelSeries-props.xml =================================================================== --- component-metadata/src/main/resources/conf/ice_cust_properties/cust-panelSeries-props.xml (revision 26333) +++ component-metadata/src/main/resources/conf/ice_cust_properties/cust-panelSeries-props.xml (working copy) @@ -58,3 +58,147 @@ + + + + Width of the entire table, for visual user agents.

+

+ Note:This attribute is only effective if the layout is 'table'. +

+ ]]> +
+ width + + APPEARANCE + + &lengthEditor; + + +
+ + + + Width (in pixels) of the border to be drawn around this table.

+

+ Note:This attribute is only effective if the layout is 'table'. +

+ ]]> +
+ border + int + + APPEARANCE + + &integerEditor; + + + minValue + new Integer(0) + + + unsetValue + new Integer(Integer.MIN_VALUE) + + +
+ + + + + Definition of how much space the user agent should leave between the + border of each cell and its contents. +

+

+ Note:This attribute is only effective if the layout is 'table'. +

+ ]]> +
+ cellpadding + + APPEARANCE + + &lengthEditor; + + +
+ + + + + Definition of how much space the user agent should leave between the + left side of the table and the leftmost column, the top of the table + and the top of the top side of the topmost row, and so on for the right + and bottom of the table. It also specifies the amount of space to leave + between cells. +

+

+ Note:This attribute is only effective if the layout is 'table'. +

+ ]]> +
+ cellspacing + + APPEARANCE + + &lengthEditor; + + +
+ + + + Specifies the layout to be used to render this PanelSeries.

+ + ]]> +
+ layout + java.lang.String + + APPEARANCE + + &stringEditor; + + +
+ + + + Specifies the number of columns in the panel.

+

+ Note:This attribute is only effective if the layout is 'table'. +

+ ]]> +
+ columns + int + + APPEARANCE + + &integerEditor; + + + minValue + new Integer(0) + + + unsetValue + new Integer(Integer.MIN_VALUE) + + +
\ No newline at end of file Index: component/src/com/icesoft/faces/component/ExtendedAttributeConstants.java =================================================================== --- component/src/com/icesoft/faces/component/ExtendedAttributeConstants.java (revision 26333) +++ component/src/com/icesoft/faces/component/ExtendedAttributeConstants.java (working copy) @@ -376,7 +376,7 @@ new String[]{ HTML.STYLE_ATTR, HTML.TITLE_ATTR, HTML.ONCLICK_ATTR, HTML.ONDBLCLICK_ATTR, HTML.ONKEYDOWN_ATTR, HTML.ONKEYPRESS_ATTR, HTML.ONKEYUP_ATTR, HTML.ONMOUSEDOWN_ATTR, HTML.ONMOUSEMOVE_ATTR, HTML.ONMOUSEOUT_ATTR, HTML.ONMOUSEOVER_ATTR, HTML.ONMOUSEUP_ATTR }; attributes[58] = (ICE_PANELPOPUP); final String[] ICE_PANELSERIES = - new String[]{ HTML.ROWS_ATTR, HTML.STYLE_ATTR }; + new String[]{ HTML.ROWS_ATTR, HTML.STYLE_ATTR, HTML.STYLE_CLASS_ATTR, HTML.CELLPADDING_ATTR, HTML.CELLSPACING_ATTR, HTML.BORDER_ATTR, HTML.WIDTH_ATTR }; attributes[59] = (ICE_PANELSERIES); final String[] ICE_PANELSTACK = new String[]{ HTML.STYLE_ATTR }; Index: component/src/com/icesoft/faces/component/panelseries/PanelSeries.java =================================================================== --- component/src/com/icesoft/faces/component/panelseries/PanelSeries.java (revision 26333) +++ component/src/com/icesoft/faces/component/panelseries/PanelSeries.java (working copy) @@ -32,14 +32,14 @@ package com.icesoft.faces.component.panelseries; -import com.icesoft.faces.component.CSS_DEFAULT; -import com.icesoft.faces.component.ext.taglib.Util; - import javax.faces.component.UIComponent; import javax.faces.component.UIData; import javax.faces.context.FacesContext; import javax.faces.el.ValueBinding; +import com.icesoft.faces.component.CSS_DEFAULT; +import com.icesoft.faces.component.ext.taglib.Util; + /** * PanelSeries is a JSF component class representing an ICEfaces panelSeries. *

The panelSeries component provides a mechanism for dynamically generating @@ -61,12 +61,15 @@ public static final String COMPONENT_FAMILY = "javax.faces.Panel"; private String style = null; private String styleClass = null; + private String layout; + private boolean columnsSet; + private int columns = 0; - public PanelSeries() { super(); setRendererType(RENDERER_TYPE); } + /* * (non-Javadoc) * @see javax.faces.component.UIComponent#getFamily() @@ -75,17 +78,13 @@ return (COMPONENT_FAMILY); } - /** *

Set the value of the styleClass property.

* * @return style class property value. */ public String getStyleClass() { - return Util.getQualifiedStyleClass(this, - styleClass, - CSS_DEFAULT.PANEL_SERIES_DEFAULT_CLASS, - "styleClass"); + return Util.getQualifiedStyleClass(this, styleClass, CSS_DEFAULT.PANEL_SERIES_DEFAULT_CLASS, "styleClass"); } /** @@ -115,12 +114,63 @@ this.style = style; } + /** + *

Set the value of the

layout

property.

+ * + * @return layout property value + */ + public String getLayout() { + if (layout != null) { + return layout; + } + ValueBinding vb = getValueBinding("layout"); + if (vb != null) { + Object value = vb.getValue(getFacesContext()); + if (value == null) { + return null; + } else { + return (String) value.toString(); + } + } + return "list"; + } + + /** + *

Set the value of the

layout

property.

+ */ + public void setLayout(String layout) { + this.layout = layout; + } + + /** + *

Set the value of the columns property.

+ * + * @return the columns property value + */ + public int getColumns() { + if (columnsSet) { + return columns; + } + ValueBinding vb = getValueBinding("columns"); + if (vb != null) { + return ((Integer) vb.getValue(getFacesContext())).intValue(); + } + return 1; + } + + /** + *

Set the value of the columns property.

+ */ + public void setColumns(int columns) { + this.columns = columns; + this.columnsSet = true; + } + /* * (non-Javadoc) * @see com.icesoft.faces.component.panelseries.UISeries#restoreChild(javax.faces.context.FacesContext, javax.faces.component.UIComponent) */ - protected void restoreChild(FacesContext facesContext, - UIComponent uiComponent) { + protected void restoreChild(FacesContext facesContext, UIComponent uiComponent) { super.restoreChild(facesContext, uiComponent); if (uiComponent instanceof UIData) { String clientId = uiComponent.getClientId(facesContext); @@ -133,8 +183,7 @@ * (non-Javadoc) * @see com.icesoft.faces.component.panelseries.UISeries#saveChild(javax.faces.context.FacesContext, javax.faces.component.UIComponent) */ - protected void saveChild(FacesContext facesContext, - UIComponent uiComponent) { + protected void saveChild(FacesContext facesContext, UIComponent uiComponent) { super.saveChild(facesContext, uiComponent); if (uiComponent instanceof UIData) { String clientId = uiComponent.getClientId(facesContext); @@ -143,22 +192,27 @@ } private transient Object values[]; + public void restoreState(FacesContext context, Object state) { - values = (Object[])state; + values = (Object[]) state; super.restoreState(context, values[0]); - style = (String)values[1]; - styleClass = (String)values[2]; + style = (String) values[1]; + styleClass = (String) values[2]; + layout = (String) values[2]; + columnsSet = ((Boolean) values[4]).booleanValue(); + columns = ((Integer) values[5]).intValue(); } public Object saveState(FacesContext context) { - if(values == null){ - values = new Object[3]; + if (values == null) { + values = new Object[6]; } values[0] = super.saveState(context); values[1] = style; values[2] = styleClass; + values[3] = layout; + values[4] = Boolean.valueOf(columnsSet); + values[5] = Integer.valueOf(columns); return values; } - - } Index: component/src/com/icesoft/faces/component/panelseries/PanelSeriesRenderer.java =================================================================== --- component/src/com/icesoft/faces/component/panelseries/PanelSeriesRenderer.java (revision 26333) +++ component/src/com/icesoft/faces/component/panelseries/PanelSeriesRenderer.java (working copy) @@ -32,68 +32,126 @@ package com.icesoft.faces.component.panelseries; -import com.icesoft.faces.context.DOMContext; -import com.icesoft.faces.renderkit.dom_html_basic.DomBasicRenderer; -import com.icesoft.faces.renderkit.dom_html_basic.HTML; -import org.w3c.dom.Element; +import java.io.IOException; +import java.util.Iterator; import javax.faces.component.UIComponent; import javax.faces.context.FacesContext; -import java.io.IOException; -import java.util.Iterator; +import org.w3c.dom.Element; +import com.icesoft.faces.component.ExtendedAttributeConstants; +import com.icesoft.faces.context.DOMContext; +import com.icesoft.faces.renderkit.dom_html_basic.DomBasicRenderer; +import com.icesoft.faces.renderkit.dom_html_basic.HTML; +import com.icesoft.faces.renderkit.dom_html_basic.PassThruAttributeRenderer; + public class PanelSeriesRenderer extends DomBasicRenderer { + private static final String[] PASSTHRU = ExtendedAttributeConstants.getAttributes(ExtendedAttributeConstants.ICE_PANELSERIES); + + /**************************************** INHERITED METHODS ****************************************/ + /* + * (non-Javadoc) + * @see javax.faces.render.Renderer#getRendersChildren() + */ public boolean getRendersChildren() { return true; } + /* + * (non-Javadoc) + * @see javax.faces.render.Renderer#encodeBegin(javax.faces.context.FacesContext, javax.faces.component.UIComponent) + */ public void encodeBegin(FacesContext facesContext, UIComponent uiComponent) throws IOException { - DOMContext domContext = - DOMContext.attachDOMContext(facesContext, uiComponent); + validateParameters(facesContext, uiComponent, PanelSeries.class); + PanelSeries pSeries = (PanelSeries) uiComponent; + DOMContext domContext = DOMContext.attachDOMContext(facesContext, pSeries); + + if (hasGridLayout(pSeries)) { + gridEncodeBegin(facesContext, domContext, pSeries); + } else { + listEncodeBegin(facesContext, domContext, pSeries); + } + } + + /* + * (non-Javadoc) + * @see javax.faces.render.Renderer#encodeChildren(javax.faces.context.FacesContext, javax.faces.component.UIComponent) + */ + public void encodeChildren(FacesContext facesContext, UIComponent uiComponent) + throws IOException { + validateParameters(facesContext, uiComponent, PanelSeries.class); + PanelSeries pList = (PanelSeries) uiComponent; + + if (hasGridLayout(pList)) { + gridEncodeChildren(facesContext, pList); + } else { + listEncodeChildren(facesContext, pList); + } + + pList.setRowIndex(-1); + } + + /* + * (non-Javadoc) + * @see com.icesoft.faces.renderkit.dom_html_basic.DomBasicRenderer#encodeEnd(javax.faces.context.FacesContext, javax.faces.component.UIComponent) + */ + public void encodeEnd(FacesContext facesContext, UIComponent uiComponent) + throws IOException { + if (hasGridLayout((PanelSeries) uiComponent)) { + validateParameters(facesContext, uiComponent, null); + } else { + super.encodeEnd(facesContext, uiComponent); + } + } + + /**************************************** LIST METHODS ****************************************/ + + /** + * Encode the root of the panel for a list layout + */ + private void listEncodeBegin(FacesContext facesContext, DOMContext domContext, PanelSeries pSeries) { if (!domContext.isInitialized()) { Element rootSpan = domContext.createElement(HTML.DIV_ELEM); domContext.setRootNode(rootSpan); - setRootElementId(facesContext, rootSpan, uiComponent); + setRootElementId(facesContext, rootSpan, pSeries); } + Element root = (Element) domContext.getRootNode(); - String style = ((PanelSeries) uiComponent).getStyle(); - if(style != null && style.length() > 0) - root.setAttribute(HTML.STYLE_ATTR, style); - else - root.removeAttribute(HTML.STYLE_ATTR); - root.setAttribute(HTML.CLASS_ATTR, - ((PanelSeries) uiComponent).getStyleClass()); - domContext.stepInto(uiComponent); + String styleClass = pSeries.getStyleClass(); + if (styleClass != null) { + root.setAttribute(HTML.CLASS_ATTR, styleClass); + } } - public void encodeChildren(FacesContext facesContext, - UIComponent uiComponent) throws IOException { - validateParameters(facesContext, uiComponent, null); - DOMContext domContext = - DOMContext.getDOMContext(facesContext, uiComponent); + /** + * Encode the root of the panel for a gridlayout + */ + private void listEncodeChildren(FacesContext facesContext, PanelSeries list) + throws IOException { + DOMContext domContext = DOMContext.getDOMContext(facesContext, list); Element root = (Element) domContext.getRootNode(); + // remove previous children DOMContext.removeChildren(root); - PanelSeries list = (PanelSeries) uiComponent; - UISeries uiList = (UISeries) uiComponent; - int rowIndex = uiList.getFirst(); - int numberOfRowsToDisplay = uiList.getRows(); + + // Data rows to display + int rowIndex = list.getFirst(); + int numberOfRowsToDisplay = list.getRows(); int countOfRowsDisplayed = 0; - while ( ( numberOfRowsToDisplay == 0 ) || - ( (numberOfRowsToDisplay > 0) && - (countOfRowsDisplayed < numberOfRowsToDisplay) ) ) - { - uiList.setRowIndex(rowIndex); - if(!uiList.isRowAvailable()){ + + while ((numberOfRowsToDisplay == 0) + || ((numberOfRowsToDisplay > 0) && (countOfRowsDisplayed < numberOfRowsToDisplay))) { + list.setRowIndex(rowIndex); + if (!list.isRowAvailable()) { break; } - Iterator childs; + if (list.getChildCount() > 0) { - childs = list.getChildren().iterator(); - while (childs.hasNext()) { - UIComponent nextChild = (UIComponent) childs.next(); + Iterator children = list.getChildren().iterator(); + while (children.hasNext()) { + UIComponent nextChild = (UIComponent) children.next(); if (nextChild.isRendered()) { domContext.setCursorParent(root); encodeParentAndChildren(facesContext, nextChild); @@ -103,7 +161,124 @@ rowIndex++; countOfRowsDisplayed++; } - uiList.setRowIndex(-1); + list.setRowIndex(-1); + } + /**************************************** GRID METHODS ****************************************/ + + /** + * Encode the beginning of the panel for a grid layout + */ + private void gridEncodeBegin(FacesContext facesContext, DOMContext domContext, PanelSeries pSeries) { + if (!domContext.isInitialized()) { + Element rootSpan = domContext.createElement(HTML.TABLE_ELEM); + domContext.setRootNode(rootSpan); + setRootElementId(facesContext, rootSpan, pSeries); + PassThruAttributeRenderer.renderHtmlAttributes(facesContext, pSeries, PASSTHRU); + } + + Element root = (Element) domContext.getRootNode(); + String styleClass = pSeries.getStyleClass(); + if (styleClass != null) { + root.setAttribute(HTML.CLASS_ATTR, styleClass); + } + domContext.stepInto(pSeries); } + + /** + * Encode children using a grid layout + */ + private void gridEncodeChildren(FacesContext facesContext, PanelSeries pList) + throws IOException { + DOMContext domContext = DOMContext.getDOMContext(facesContext, pList); + Element root = (Element) domContext.getRootNode(); + // remove previous children + DOMContext.removeChildren(root); + + // Create table body + Element tbody = domContext.createElement(HTML.TBODY_ELEM); + root.appendChild(tbody); + Element tr = null; + + // Display vars + int numberOfColumns = getConvertedColumnAttribute(pList); + int columnIndex = numberOfColumns; // this initial value invoked initialization of first row + + // Data vars - these refer to "data rows" in the model, not html rows + int rowIndex = pList.getFirst(); + int numberOfRowsToDisplay = pList.getRows(); + int countOfRowsDisplayed = 0; + + while ((numberOfRowsToDisplay == 0) + || ((numberOfRowsToDisplay > 0) && (countOfRowsDisplayed < numberOfRowsToDisplay))) { + pList.setRowIndex(rowIndex); + if (!pList.isRowAvailable()) { + break; + } + + // Render children inside the tbody element. + // Based on the value of the "columns" attribute, create a new row every + // time a columns-worth of children has been rendered. + // Children with attribute "rendered" == false are not rendered and do + // not occupy a table cell. + if (pList.getChildCount() > 0) { + Iterator children = pList.getChildren().iterator(); + if (children == null || !children.hasNext()) { + tr = domContext.createElement(HTML.TR_ELEM); + tr.setAttribute(HTML.STYLE_ATTR, "display: none;"); + tr.appendChild(domContext.createElement(HTML.TD_ELEM)); + tbody.appendChild(tr); + } else { + while (children.hasNext()) { + UIComponent nextChild = (UIComponent) children.next(); + if (!nextChild.isRendered()) { + continue; + } + + // detect whether a new row is needed + if (columnIndex >= numberOfColumns) { + tr = domContext.createElement(HTML.TR_ELEM); + tbody.appendChild(tr); + columnIndex = 0; + } + // create the td for this child + Element td = domContext.createElement(HTML.TD_ELEM); + tr.appendChild(td); + + domContext.setCursorParent(td); + encodeParentAndChildren(facesContext, nextChild); + columnIndex++; + } + } + } + + rowIndex++; + countOfRowsDisplayed++; + } + pList.setRowIndex(-1); + domContext.stepOver(); + } + + /**************************************** MISC METHODS ****************************************/ + + /** + * @return true if the provided PanelSeries has a 'grid' Layout + */ + private boolean hasGridLayout(PanelSeries pSeries) { + return "grid".equals(pSeries.getLayout()); + } + + /** + * @return the converted number of columns for a PanelSeries (1 by default) + */ + private int getConvertedColumnAttribute(PanelSeries pSeries) { + int convertedColumnAttribute = 1; // default + Object columnAttribute = pSeries.getAttributes().get("columns"); + int value; + if (columnAttribute != null && columnAttribute instanceof Number + && (value = ((Number) columnAttribute).intValue()) > 0) { + convertedColumnAttribute = value; + } + return (convertedColumnAttribute); + } } Index: component/src/com/icesoft/faces/component/panelseries/UISeries.java =================================================================== --- component/src/com/icesoft/faces/component/panelseries/UISeries.java (revision 26333) +++ component/src/com/icesoft/faces/component/panelseries/UISeries.java (working copy) @@ -361,7 +361,7 @@ * * @return */ - private DataModel getDataModel() { + protected DataModel getDataModel() { if (null != this.dataModel) { return (dataModel); }