Hi,
the attachment contains the patches and new files (based on the current cvs) for a new component to make cross tables work.
An example is also included ;)
Mathias
Index: conf/faces-config.xml
===================================================================
RCS file: /home/cvspublic/incubator-myfaces/conf/faces-config.xml,v
retrieving revision 1.114
diff -u -r1.114 faces-config.xml
--- conf/faces-config.xml 15 Mar 2005 21:11:39 -0000 1.114
+++ conf/faces-config.xml 24 Mar 2005 13:59:56 -0000
@@ -281,6 +281,10 @@
<component-class>org.apache.myfaces.custom.swapimage.HtmlSwapImage</component-class>
</component>
+ <component>
+ <component-type>org.apache.myfaces.Columns</component-type>
+
<component-class>org.apache.myfaces.component.UIColumns</component-class>
+ </component>
<!-- additional "by type" converters -->
Index: HtmlDataTable.java
===================================================================
RCS file:
/home/cvspublic/incubator-myfaces/src/components/org/apache/myfaces/component/html/ext/HtmlDataTable.java,v
retrieving revision 1.19
diff -u -r1.19 HtmlDataTable.java
--- HtmlDataTable.java 21 Mar 2005 12:33:46 -0000 1.19
+++ HtmlDataTable.java 24 Mar 2005 14:02:29 -0000
@@ -17,6 +17,7 @@
import org.apache.myfaces.component.UserRoleAware;
import org.apache.myfaces.component.UserRoleUtils;
+import org.apache.myfaces.component.UIColumns;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -28,6 +29,7 @@
import javax.faces.event.FacesEvent;
import javax.faces.model.DataModel;
import javax.faces.render.Renderer;
+
import java.io.IOException;
import java.sql.ResultSet;
import java.util.Iterator;
@@ -94,6 +96,10 @@
{
private static final Log log = LogFactory.getLog(HtmlDataTable.class);
+ private static final int PROCESS_DECODES = 1;
+ private static final int PROCESS_VALIDATORS = 2;
+ private static final int PROCESS_UPDATES = 3;
+
private static final boolean DEFAULT_SORTASCENDING = true;
private static final Class OBJECT_ARRAY_CLASS = (new Object[0]).getClass();
@@ -186,12 +192,122 @@
public void processDecodes(FacesContext context)
{
+ if(!isRendered())
+ {
+ return;
+ }
super.processDecodes(context);
+ setRowIndex(-1);
+ processColumnsFacets(context, PROCESS_DECODES);
+ processColumnsChildren(context, PROCESS_DECODES);
+ setRowIndex(-1);
+ }
+
+ /**
+ * @param context
+ * @param processAction
+ */
+ private void processColumnsChildren(FacesContext context, int
processAction)
+ {
+ int first = getFirst();
+ int rows = getRows();
+ int last;
+ if (rows == 0)
+ {
+ last = getRowCount();
+ }
+ else
+ {
+ last = first + rows;
+ }
+ for (int rowIndex = first; rowIndex < last; rowIndex++)
+ {
+ setRowIndex(rowIndex);
+ if (isRowAvailable())
+ {
+ for (Iterator it = getChildren().iterator(); it.hasNext();)
+ {
+ UIComponent child = (UIComponent) it.next();
+ if (child instanceof UIColumns)
+ {
+ if (child.isRendered())
+ {
+ UIColumns columns = (UIColumns) child;
+ for (int colIndex = 0, size = columns.getRowCount(); colIndex
< size; colIndex++)
+ {
+ columns.setRowIndex(colIndex);
+ for (Iterator columnChildIter =
child.getChildren().iterator(); columnChildIter
+ .hasNext();)
+ {
+ UIComponent columnChild = (UIComponent)
columnChildIter.next();
+ process(context, columnChild, processAction);
+ }
+ }
+ columns.setRowIndex(-1);
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ /**
+ * @param context
+ * @param processAction
+ */
+ private void processColumnsFacets(FacesContext context, int processAction)
+ {
+ for (Iterator childIter = getChildren().iterator(); childIter.hasNext();)
+ {
+ UIComponent child = (UIComponent) childIter.next();
+ if (child instanceof UIColumns)
+ {
+ if(child.isRendered())
+ {
+ UIColumns columns = (UIColumns) child;
+ for (int i = 0, size = columns.getRowCount(); i < size; i++)
+ {
+ columns.setRowIndex(i);
+ for (Iterator facetsIter =
child.getFacets().values().iterator(); facetsIter.hasNext();)
+ {
+ UIComponent facet = (UIComponent) facetsIter.next();
+ process(context, facet, processAction);
+ }
+ }
+ columns.setRowIndex(-1);
+ }
+ }
+ }
+ }
+
+ private void process(FacesContext context, UIComponent component, int
processAction)
+ {
+ switch (processAction)
+ {
+ case PROCESS_DECODES :
+ component.processDecodes(context);
+ break;
+ case PROCESS_VALIDATORS :
+ component.processValidators(context);
+ break;
+ case PROCESS_UPDATES :
+ component.processUpdates(context);
+ break;
+ }
}
public void processValidators(FacesContext context)
{
- super.processValidators(context);
+ if(!isRendered())
+ {
+ return;
+ }
+ super.processValidators(context);
+ setRowIndex(-1);
+ processColumnsFacets(context, PROCESS_VALIDATORS);
+ processColumnsChildren(context, PROCESS_VALIDATORS);
+ setRowIndex(-1);
}
public Object processSaveState(FacesContext context)
@@ -206,7 +322,15 @@
public void processUpdates(FacesContext context)
{
+ if(!isRendered())
+ {
+ return;
+ }
super.processUpdates(context);
+ setRowIndex(-1);
+ processColumnsFacets(context, PROCESS_UPDATES);
+ processColumnsChildren(context, PROCESS_UPDATES);
+ setRowIndex(-1);
if (_isDataModelRestored)
{
Index: HtmlTableRendererBase.java
===================================================================
RCS file:
/home/cvspublic/incubator-myfaces/src/share/org/apache/myfaces/renderkit/html/HtmlTableRendererBase.java,v
retrieving revision 1.8
diff -u -r1.8 HtmlTableRendererBase.java
--- HtmlTableRendererBase.java 11 Feb 2005 16:03:00 -0000 1.8
+++ HtmlTableRendererBase.java 24 Mar 2005 14:05:09 -0000
@@ -19,6 +19,7 @@
import org.apache.myfaces.renderkit.RendererUtils;
import org.apache.myfaces.util.ArrayUtils;
import org.apache.myfaces.util.StringUtils;
+import org.apache.myfaces.component.UIColumns;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -148,10 +149,24 @@
for (int j = 0, size = component.getChildCount(); j < size; j++)
{
UIComponent child = (UIComponent) children.get(j);
- if (child instanceof UIColumn && ((UIColumn)
child).isRendered())
+ if(child.isRendered())
{
- String columnStyle = styles.getColumnStyle(j);
- renderColumnBody(facesContext, writer, uiData, (UIColumn)
child, columnStyle);
+ if (child instanceof UIColumn)
+ {
+ String columnStyle = styles.getColumnStyle(j);
+ renderColumnBody(facesContext, writer, uiData,
child, columnStyle);
+ }
+ else if (child instanceof UIColumns)
+ {
+ UIColumns columns = (UIColumns) child;
+ for (int k = 0, colSize = columns.getRowCount(); k <
colSize; k++)
+ {
+ columns.setRowIndex(k);
+ String columnStyle = styles.getColumnStyle(j);
+ renderColumnBody(facesContext, writer, uiData,
child, columnStyle);
+ }
+ columns.setRowIndex(-1);
+ }
}
}
renderRowEnd(facesContext, writer, uiData);
@@ -166,7 +181,7 @@
* @param facesContext the <code>FacesContext</code>.
* @param writer the <code>ResponseWriter</code>.
* @param uiData the <code>UIData</code> being rendered.
- * @param column the <code>UIColumn</code> to render.
+ * @param component the <code>UIComponent</code> to render.
* @param columnStyleClass the styleClass of the <code>UIColumn</code> or
<code>null</code> if
* there is none.
* @throws IOException if an exception occurs.
@@ -175,7 +190,7 @@
FacesContext facesContext,
ResponseWriter writer,
UIData uiData,
- UIColumn column,
+ UIComponent component,
String columnStyleClass) throws IOException
{
writer.startElement(HTML.TD_ELEM, uiData);
@@ -184,7 +199,7 @@
writer.writeAttribute(HTML.CLASS_ATTR,
columnStyleClass, null);
}
- RendererUtils.renderChild(facesContext, column);
+ RendererUtils.renderChild(facesContext, component);
writer.endElement(HTML.TD_ELEM);
}
@@ -291,14 +306,26 @@
for (Iterator it = component.getChildren().iterator(); it.hasNext();)
{
UIComponent uiComponent = (UIComponent) it.next();
- if (uiComponent instanceof UIColumn && ((UIColumn)
uiComponent).isRendered())
+ if(uiComponent.isRendered())
{
- colspan++;
- if (!hasColumnFacet)
- {
- hasColumnFacet = header ? ((UIColumn)
uiComponent).getHeader() != null : ((UIColumn) uiComponent)
- .getFooter() != null;
- }
+ if (uiComponent instanceof UIColumn)
+ {
+ colspan++;
+ if (!hasColumnFacet)
+ {
+ hasColumnFacet = header ? ((UIColumn)
uiComponent).getHeader() != null : ((UIColumn) uiComponent)
+ .getFooter() != null;
+ }
+ }
+ else if (uiComponent instanceof UIColumns)
+ {
+ UIColumns columns = (UIColumns) uiComponent;
+ colspan += columns.getRowCount();
+ if (!hasColumnFacet)
+ {
+ hasColumnFacet = header ? columns.getHeader() != null :
columns.getFooter() != null;
+ }
+ }
}
}
@@ -420,8 +447,8 @@
writer.endElement(HTML.TR_ELEM);
}
- private void renderColumnHeaderOrFooterRow(FacesContext facesContext,
ResponseWriter writer, UIComponent component,
- String styleClass, boolean header) throws IOException
+ private void renderColumnHeaderOrFooterRow(FacesContext facesContext,
ResponseWriter writer,
+ UIComponent component, String styleClass, boolean header) throws
IOException
{
HtmlRendererUtils.writePrettyLineSeparator(facesContext);
@@ -429,35 +456,76 @@
for (Iterator it = component.getChildren().iterator(); it.hasNext();)
{
UIComponent uiComponent = (UIComponent) it.next();
- if (uiComponent instanceof UIColumn && ((UIColumn)
uiComponent).isRendered())
+ if(uiComponent.isRendered())
{
- if (header)
- {
- renderColumnHeaderCell(facesContext, writer, (UIColumn)
uiComponent, styleClass, 0);
- }
- else
- {
- renderColumnFooterCell(facesContext, writer, (UIColumn)
uiComponent, styleClass, 0);
- }
+ if (uiComponent instanceof UIColumn)
+ {
+ if (header)
+ {
+ renderColumnHeaderCell(facesContext, writer,
uiComponent,
+ ((UIColumn) uiComponent).getHeader(), styleClass, 0);
+ }
+ else
+ {
+ renderColumnFooterCell(facesContext, writer,
uiComponent,
+ ((UIColumn) uiComponent).getFooter(), styleClass, 0);
+ }
+ }
+ else if (uiComponent instanceof UIColumns)
+ {
+ UIColumns columns = (UIColumns) uiComponent;
+ for (int i = 0, size = columns.getRowCount(); i < size; i++)
+ {
+ columns.setRowIndex(i);
+ if (header)
+ {
+ renderColumnHeaderCell(facesContext, writer,
columns, columns.getHeader(),
+ styleClass, 0);
+ }
+ else
+ {
+ renderColumnFooterCell(facesContext, writer,
columns, columns.getFooter(),
+ styleClass, 0);
+ }
+ }
+ columns.setRowIndex(-1);
+ }
}
}
writer.endElement(HTML.TR_ELEM);
}
- /**
+ /**
+ * Renders the header facet for the given <code>UIColumn</code>.
+ * @param facesContext the <code>FacesContext</code>.
+ * @param writer the <code>ResponseWriter</code>.
+ * @param uiColumn the <code>UIColumn</code>.
+ * @param headerStyleClass the styleClass of the header facet.
+ * @param colspan the colspan for the tableData element in which the
header facet
+ * will be wrapped.
+ * @throws IOException
+ */
+ protected void renderColumnHeaderCell(FacesContext facesContext,
ResponseWriter writer, UIColumn uiColumn,
+ String headerStyleClass, int colspan) throws IOException
+ {
+ renderColumnHeaderCell(facesContext, writer, uiColumn,
uiColumn.getHeader(), headerStyleClass, colspan);
+ }
+
+ /**
* Renders the header facet for the given <code>UIColumn</code>.
* @param facesContext the <code>FacesContext</code>.
* @param writer the <code>ResponseWriter</code>.
- * @param uiColumn the <code>UIColumn</code>.
+ * @param uiComponent the <code>UIComponent</code> to render the facet
for.
+ * @param facet the <code>UIComponent</code> to render as facet.
* @param headerStyleClass the styleClass of the header facet.
* @param colspan the colspan for the tableData element in which the
header facet
* will be wrapped.
* @throws IOException
*/
- protected void renderColumnHeaderCell(FacesContext facesContext,
ResponseWriter writer, UIColumn uiColumn,
- String headerStyleClass, int colspan) throws IOException
+ protected void renderColumnHeaderCell(FacesContext facesContext,
ResponseWriter writer, UIComponent uiComponent,
+ UIComponent facet, String headerStyleClass, int colspan) throws
IOException
{
- writer.startElement(HTML.TH_ELEM, uiColumn);
+ writer.startElement(HTML.TH_ELEM, uiComponent);
if (colspan > 1)
{
writer.writeAttribute(HTML.COLSPAN_ATTR, new Integer(colspan),
null);
@@ -466,7 +534,6 @@
{
writer.writeAttribute(HTML.CLASS_ATTR, headerStyleClass, null);
}
- UIComponent facet = uiColumn.getHeader();
if (facet != null)
{
RendererUtils.renderChild(facesContext, facet);
@@ -474,20 +541,37 @@
writer.endElement(HTML.TH_ELEM);
}
+ /**
+ * Renders the footer facet for the given <code>UIColumn</code>.
+ * @param facesContext the <code>FacesContext</code>.
+ * @param writer the <code>ResponseWriter</code>.
+ * @param uiColumn the <code>UIComponent</code>.
+ * @param footerStyleClass the styleClass of the footer facet.
+ * @param colspan the colspan for the tableData element in which the
footer facet
+ * will be wrapped.
+ * @throws IOException
+ */
+ protected void renderColumnFooterCell(FacesContext facesContext,
ResponseWriter writer, UIColumn uiColumn,
+ String footerStyleClass, int colspan) throws IOException
+ {
+ renderColumnFooterCell(facesContext, writer, uiColumn,
uiColumn.getFooter(), footerStyleClass, colspan);
+ }
+
/**
* Renders the footer facet for the given <code>UIColumn</code>.
* @param facesContext the <code>FacesContext</code>.
* @param writer the <code>ResponseWriter</code>.
- * @param uiColumn the <code>UIColumn</code>.
+ * @param uiComponent the <code>UIComponent</code> to render the facet
for.
+ * @param facet the <code>UIComponent</code> to render as facet.
* @param footerStyleClass the styleClass of the footer facet.
* @param colspan the colspan for the tableData element in which the
footer facet
* will be wrapped.
* @throws IOException
*/
- protected void renderColumnFooterCell(FacesContext facesContext,
ResponseWriter writer, UIColumn uiColumn,
- String footerStyleClass, int colspan) throws IOException
+ protected void renderColumnFooterCell(FacesContext facesContext,
ResponseWriter writer, UIComponent uiComponent,
+ UIComponent facet, String footerStyleClass, int colspan) throws
IOException
{
- writer.startElement(HTML.TD_ELEM, uiColumn);
+ writer.startElement(HTML.TD_ELEM, uiComponent);
if (colspan > 1)
{
writer.writeAttribute(HTML.COLSPAN_ATTR, new Integer(colspan),
null);
@@ -496,7 +580,6 @@
{
writer.writeAttribute(HTML.CLASS_ATTR, footerStyleClass, null);
}
- UIComponent facet = uiColumn.getFooter();
if (facet != null)
{
RendererUtils.renderChild(facesContext, facet);
Index: tlds/myfaces_ext.tld
===================================================================
RCS file: /home/cvspublic/incubator-myfaces/tlds/myfaces_ext.tld,v
retrieving revision 1.182
diff -u -r1.182 myfaces_ext.tld
--- tlds/myfaces_ext.tld 22 Mar 2005 02:13:28 -0000 1.182
+++ tlds/myfaces_ext.tld 24 Mar 2005 14:00:02 -0000
@@ -2153,4 +2153,24 @@
<attribute><name>onkeyup</name> <required>false</required>
<rtexprvalue>false</rtexprvalue></attribute>
</tag>
+ <!-- columns -->
+ <tag>
+ <name>columns</name>
+
<tag-class>org.apache.myfaces.custom.crosstable.HtmlColumnsTag</tag-class>
+ <body-content>JSP</body-content>
+ &ui_component_attributes;
+ &ui_column_attributes;
+ <attribute>
+ <name>value</name>
+ <required>true</required>
+ <rtexprvalue>false</rtexprvalue>
+ <description>Supported types see JSF Spec 4.1.3</description>
+ </attribute>
+ <attribute>
+ <name>var</name>
+ <required>true</required>
+ <rtexprvalue>false</rtexprvalue>
+ </attribute>
+ </tag>
+
</taglib>
Index: webapps/examples/WEB-INF/examples-config.xml
===================================================================
RCS file:
/home/cvspublic/incubator-myfaces/webapps/examples/WEB-INF/examples-config.xml,v
retrieving revision 1.1
diff -u -r1.1 examples-config.xml
--- webapps/examples/WEB-INF/examples-config.xml 12 Mar 2005 11:40:07
-0000 1.1
+++ webapps/examples/WEB-INF/examples-config.xml 24 Mar 2005 14:00:03
-0000
@@ -241,7 +241,15 @@
<managed-bean-class>java.util.HashMap</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
-
+
+
+ <!-- Managed Beans for crosstable example -->
+
+ <managed-bean>
+ <managed-bean-name>crossDataTable</managed-bean-name>
+
<managed-bean-class>org.apache.myfaces.examples.crosstable.DataBean</managed-bean-class>
+ <managed-bean-scope>session</managed-bean-scope>
+ </managed-bean>
<navigation-rule>
@@ -413,6 +421,11 @@
<to-view-id>/selectOneCountry.jsp</to-view-id>
</navigation-case>
+ <navigation-case>
+ <from-outcome>go_crossDataTable</from-outcome>
+ <to-view-id>/crossDataTable.jsp</to-view-id>
+ </navigation-case>
+
</navigation-rule>
<navigation-rule>
Index: webapps/examples/inc/navigation.jsp
===================================================================
RCS file:
/home/cvspublic/incubator-myfaces/webapps/examples/inc/navigation.jsp,v
retrieving revision 1.1
diff -u -r1.1 navigation.jsp
--- webapps/examples/inc/navigation.jsp 12 Mar 2005 11:40:06 -0000 1.1
+++ webapps/examples/inc/navigation.jsp 24 Mar 2005 14:00:03 -0000
@@ -39,6 +39,7 @@
<x:commandNavigation id="nav_2_4_17"
value="#{example_messages['nav_swapimage']}" action="go_swapimage" />
<x:commandNavigation id="nav_2_4_18"
value="#{example_messages['nav_forceId']}" action="go_forceId" />
<x:commandNavigation id="nav_2_4_19"
value="#{example_messages['nav_selectOneCountry']}"
action="go_selectOneCountry" />
+ <x:commandNavigation id="nav_2_4_20"
value="#{example_messages['nav_crossDataTable']}" action="go_crossDataTable" />
</x:commandNavigation>
</x:commandNavigation>
<x:commandNavigation id="nav_3"
value="#{example_messages['nav_Documentation']}" >
Index:
webapps/src/org/apache/myfaces/examples/resource/example_messages.properties
===================================================================
RCS file:
/home/cvspublic/incubator-myfaces/webapps/src/org/apache/myfaces/examples/resource/example_messages.properties,v
retrieving revision 1.1
diff -u -r1.1 example_messages.properties
---
webapps/src/org/apache/myfaces/examples/resource/example_messages.properties
12 Mar 2005 11:40:06 -0000 1.1
+++
webapps/src/org/apache/myfaces/examples/resource/example_messages.properties
24 Mar 2005 14:00:04 -0000
@@ -37,8 +37,9 @@
nav_HtmlEditor = Html Editor
nav_forceId = ForceId
nav_selectOneCountry= Select a country box
-
nav_swapimage = SwapImage
+nav_crossDataTable = Crosstable
+
# buttons
button_save = Save
@@ -162,4 +163,9 @@
css_msg=A simple test for the
forceOne=Value 1
-forceTwo=Value 2 (with forceId)
\ No newline at end of file
+forceTwo=Value 2 (with forceId)
+
+crosstable_field_column=column label
+crosstable_add_column=add a column
+crosstable_remove_column=remove the column
+crosstable_save_values=save values
\ No newline at end of file
Index:
webapps/src/org/apache/myfaces/examples/resource/example_messages_de.properties
===================================================================
RCS file:
/home/cvspublic/incubator-myfaces/webapps/src/org/apache/myfaces/examples/resource/example_messages_de.properties,v
retrieving revision 1.1
diff -u -r1.1 example_messages_de.properties
---
webapps/src/org/apache/myfaces/examples/resource/example_messages_de.properties
12 Mar 2005 11:40:06 -0000 1.1
+++
webapps/src/org/apache/myfaces/examples/resource/example_messages_de.properties
24 Mar 2005 14:00:04 -0000
@@ -32,6 +32,7 @@
nav_newspaperTable = Newspaper Table
nav_forceId = ForceId
nav_swapimage = SwapImage
+nav_crossDataTable = Kreuztabelle
# buttons
@@ -105,3 +106,8 @@
forceOne=Eingabe 1
forceTwo=Eingabe 2 (mit forceId)
+
+crosstable_field_column=Spaltenname
+crosstable_add_column=Spalte hinzuf�gen
+crosstable_remove_column=Spalte l�schen
+crosstable_save_values=Werte speichern
\ No newline at end of file
Index: src/components/org/apache/myfaces/custom/crosstable/HtmlColumnsTag.java
===================================================================
RCS file:
src/components/org/apache/myfaces/custom/crosstable/HtmlColumnsTag.java
diff -N src/components/org/apache/myfaces/custom/crosstable/HtmlColumnsTag.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/components/org/apache/myfaces/custom/crosstable/HtmlColumnsTag.java
1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed 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.crosstable;
+
+import javax.faces.component.UIComponent;
+
+import org.apache.myfaces.component.UIColumns;
+import org.apache.myfaces.renderkit.JSFAttr;
+import org.apache.myfaces.taglib.html.HtmlComponentBodyTagBase;
+
+/**
+ * @author Mathias Broekelmann (latest modification by $Author: Mathias
Broekelmann $)
+ * @version $Revision$ $Date$
+ * $Log$
+ */
+public class HtmlColumnsTag extends HtmlComponentBodyTagBase
+{
+ private String mVar;
+
+ /**
+ * @see javax.faces.webapp.UIComponentTag#getComponentType()
+ */
+ public String getComponentType()
+ {
+ return UIColumns.COMPONENT_TYPE;
+ }
+
+ /**
+ * @see javax.faces.webapp.UIComponentTag#getRendererType()
+ */
+ public String getRendererType()
+ {
+ return null;
+ }
+
+ public void setVar(String var)
+ {
+ mVar = var;
+ }
+
+ protected void setProperties(UIComponent component)
+ {
+ super.setProperties(component);
+
+ setStringProperty(component, JSFAttr.VAR_ATTR, mVar);
+ }
+}
Index: src/share/org/apache/myfaces/component/UIColumns.java
===================================================================
RCS file: src/share/org/apache/myfaces/component/UIColumns.java
diff -N src/share/org/apache/myfaces/component/UIColumns.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/share/org/apache/myfaces/component/UIColumns.java 1 Jan 1970
00:00:00 -0000
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed 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.component;
+
+import javax.faces.component.UIData;
+
+/**
+ * @author Mathias Broekelmann (latest modification by $Author: Mathias
Broekelmann $)
+ * @version $Revision$ $Date$
+ * $Log$
+ */
+public class UIColumns extends UIData
+{
+ public static final String COMPONENT_TYPE = "org.apache.myfaces.Columns";
+ public static final String COMPONENT_FAMILY = UIData.COMPONENT_FAMILY;
+
+ /**
+ *
+ */
+ public UIColumns()
+ {
+ super();
+ }
+
+ /**
+ * @see javax.faces.component.UIComponentBase#getRendererType()
+ */
+ public String getRendererType()
+ {
+ return null;
+ }
+
+ /**
+ * @see javax.faces.component.UIComponent#getFamily()
+ */
+ public String getFamily()
+ {
+ return COMPONENT_FAMILY;
+ }
+}
Index: webapps/examples/crossDataTable.jsp
===================================================================
RCS file: webapps/examples/crossDataTable.jsp
diff -N webapps/examples/crossDataTable.jsp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ webapps/examples/crossDataTable.jsp 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,130 @@
+<%@ page session="false" contentType="text/html;charset=utf-8"%>
+<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
+<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
+<%@ taglib uri="http://myfaces.apache.org/extensions" prefix="x"%>
+<html>
+
+<!--
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed 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.
+ */
+//-->
+
+<[EMAIL PROTECTED] file="inc/head.inc"%>
+
+<body>
+
+<!--
+managed beans used:
+ countryList
+-->
+
+<f:view>
+
+ <f:loadBundle
+ basename="org.apache.myfaces.examples.resource.example_messages"
+ var="example_messages" />
+
+ <x:panelLayout id="page" layout="#{globalOptions.pageLayout}"
+ styleClass="pageLayout" headerClass="pageHeader"
+ navigationClass="pageNavigation" bodyClass="pageBody"
+ footerClass="pageFooter">
+
+ <f:facet name="header">
+ <f:subview id="header">
+ <jsp:include page="inc/page_header.jsp" />
+ </f:subview>
+ </f:facet>
+
+ <f:facet name="navigation">
+ <f:subview id="menu">
+ <jsp:include page="inc/navigation.jsp" />
+ </f:subview>
+ </f:facet>
+
+ <f:facet name="body">
+ <h:form>
+ <h:panelGroup id="body">
+
+ <h:panelGrid columns="1">
+ <h:commandLink
rendered="#{!crossDataTable.editValues}" action="#{crossDataTable.editValues}"
+ immediate="true">
+ <h:outputText
value="#{example_messages['country_edit_table']}"
+ styleClass="standard" />
+ </h:commandLink>
+ <h:panelGrid
rendered="#{!crossDataTable.editValues}" columns="3">
+ <h:outputLabel
for="columnLabel" value="#{example_messages['crosstable_field_column']}"/>
+ <h:inputText id="columnLabel"
value="#{crossDataTable.columnLabel}" />
+ <h:commandLink
action="#{crossDataTable.addColumn}">
+ <h:outputText
value="#{example_messages['crosstable_add_column']}"
+
styleClass="standard" />
+ </h:commandLink>
+ </h:panelGrid>
+ <h:commandLink
rendered="#{crossDataTable.editValues}" action="#{crossDataTable.saveValues}">
+ <h:outputText
value="#{example_messages['crosstable_save_values']}"
+ styleClass="standard" />
+ </h:commandLink>
+ </h:panelGrid>
+ <f:verbatim>
+ <br>
+ </f:verbatim>
+
+ <x:dataTable id="data"
styleClass="standardTable"
+ headerClass="standardTable_Header"
+ footerClass="standardTable_Header"
+
rowClasses="standardTable_Row1,standardTable_Row2"
+ columnClasses="standardTable_Column"
var="country"
+
value="#{crossDataTable.countryDataModel}" preserveDataModel="false">
+ <h:column>
+ <f:facet name="header">
+ <h:outputText
value="#{example_messages['label_country_name']}" />
+ </f:facet>
+ <h:outputText
value="#{country.name}" />
+ </h:column>
+
+ <x:columns
value="#{crossDataTable.columnDataModel}" var="column">
+ <f:facet name="header">
+ <h:panelGroup>
+ <h:outputText
value="#{column} " />
+ <h:commandLink
action="#{crossDataTable.removeColumn}">
+
<h:outputText value="-" title="#{example_messages['crosstable_remove_column']}"
/>
+ </h:commandLink>
+ </h:panelGroup>
+ </f:facet>
+ <h:outputText
rendered="#{!crossDataTable.editValues}"
+
value="#{crossDataTable.columnValue}" />
+ <h:inputText
rendered="#{crossDataTable.editValues}"
+
value="#{crossDataTable.columnValue}" />
+ </x:columns>
+
+ </x:dataTable>
+
+ <f:verbatim>
+ <br>
+ </f:verbatim>
+
+ </h:panelGroup>
+ </h:form>
+ </f:facet>
+
+ <[EMAIL PROTECTED] file="inc/page_footer.jsp"%>
+
+ </x:panelLayout>
+
+</f:view>
+
+</body>
+
+</html>
Index: webapps/src/org/apache/myfaces/examples/crosstable/DataBean.java
===================================================================
RCS file: webapps/src/org/apache/myfaces/examples/crosstable/DataBean.java
diff -N webapps/src/org/apache/myfaces/examples/crosstable/DataBean.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ webapps/src/org/apache/myfaces/examples/crosstable/DataBean.java 1 Jan
1970 00:00:00 -0000
@@ -0,0 +1,212 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed 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.examples.crosstable;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.faces.model.DataModel;
+import javax.faces.model.ListDataModel;
+
+import org.apache.myfaces.examples.listexample.SimpleCountry;
+import org.apache.myfaces.examples.listexample.SimpleCountryList;
+
+/**
+ * @author Mathias Broekelmann (latest modification by $Author$)
+ * @version $Revision$ $Date$
+ */
+public class DataBean extends SimpleCountryList
+{
+ private DataModel mColumns;
+ private DataModel mCountryDataModel;
+ private Map mValueMap = new HashMap();
+ private boolean mEditValues;
+ private String mColumnLabel;
+
+ /**
+ *
+ */
+ public DataBean()
+ {
+ super();
+ }
+
+ public boolean isEditValues()
+ {
+ return mEditValues;
+ }
+
+ public String editValues()
+ {
+ mEditValues = true;
+ return null;
+ }
+
+ public String saveValues()
+ {
+ mEditValues = false;
+ return null;
+ }
+
+ public String addColumn()
+ {
+ if (mColumnLabel != null)
+ {
+ List columns = (List) getColumnDataModel().getWrappedData();
+ columns.add(mColumnLabel);
+ }
+ return null;
+ }
+
+ public String removeColumn()
+ {
+ if (mColumns != null && mColumns.isRowAvailable())
+ {
+ Object column = mColumns.getRowData();
+ List columns = (List) getColumnDataModel().getWrappedData();
+ columns.remove(column);
+ }
+ return null;
+ }
+
+ public String getColumnLabel()
+ {
+ return mColumnLabel;
+ }
+
+ public void setColumnLabel(String label)
+ {
+ mColumnLabel = label;
+ }
+
+ public DataModel getCountryDataModel()
+ {
+ if (mCountryDataModel == null)
+ {
+ mCountryDataModel = new ListDataModel(getCountries());
+ }
+ return mCountryDataModel;
+ }
+
+ public DataModel getColumnDataModel()
+ {
+ if (mColumns == null)
+ {
+ String[] result = new String[] {"2002", "2003", "2004"};
+ mColumns = new ListDataModel(new ArrayList(Arrays.asList(result)));
+ }
+ return mColumns;
+ }
+
+ public String getColumnValue()
+ {
+ DataModel countryDataModel = getCountryDataModel();
+ if (countryDataModel.isRowAvailable())
+ {
+ SimpleCountry row = (SimpleCountry) countryDataModel.getRowData();
+ DataModel columnDataModel = getColumnDataModel();
+ if (columnDataModel.isRowAvailable())
+ {
+ Object column = columnDataModel.getRowData();
+ Object key = new RowColumnKey(new Long(row.getId()), column);
+ if (!mValueMap.containsKey(key))
+ {
+ // initialize with random value
+ String randomValue = String.valueOf((int) (Math.random() * 5000) +
5000);
+ mValueMap.put(key, randomValue);
+ }
+ return (String) mValueMap.get(key);
+ }
+ }
+ return null;
+ }
+
+ public void setColumnValue(String value)
+ {
+ DataModel countryDataModel = getCountryDataModel();
+ if (countryDataModel.isRowAvailable())
+ {
+ SimpleCountry row = (SimpleCountry) countryDataModel.getRowData();
+ DataModel columnDataModel = getColumnDataModel();
+ if (columnDataModel.isRowAvailable())
+ {
+ Object column = columnDataModel.getRowData();
+ Object key = new RowColumnKey(new Long(row.getId()), column);
+ mValueMap.put(key, value);
+ }
+ }
+ }
+
+ private class RowColumnKey
+ {
+ private final Object mRow;
+ private final Object mColumn;
+
+ /**
+ * @param row
+ * @param column
+ */
+ public RowColumnKey(Object row, Object column)
+ {
+ mRow = row;
+ mColumn = column;
+ }
+
+ /**
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public boolean equals(Object obj)
+ {
+ if (obj == null)
+ {
+ return false;
+ }
+ if (obj == this)
+ {
+ return true;
+ }
+ if (obj instanceof RowColumnKey)
+ {
+ RowColumnKey other = (RowColumnKey) obj;
+ return other.mRow.equals(mRow) && other.mColumn.equals(mColumn);
+ }
+ return super.equals(obj);
+ }
+
+ /**
+ * @see java.lang.Object#hashCode()
+ */
+ public int hashCode()
+ {
+ return (37 * 3 + mRow.hashCode()) * (37 * 3 + mColumn.hashCode());
+ }
+
+ /**
+ * @see java.lang.Object#toString()
+ */
+ public String toString()
+ {
+ return mRow.toString() + "," + mColumn.toString();
+ }
+ }
+}
+
+/**
+ * $Log$
+ */
