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 2012/10/07 06:37:18 UTC

svn commit: r1395211 - in /myfaces/tomahawk/trunk/core20/src: main/java/org/apache/myfaces/component/html/ext/ test/java/org/apache/myfaces/component/html/ext/

Author: lu4242
Date: Sun Oct  7 04:37:18 2012
New Revision: 1395211

URL: http://svn.apache.org/viewvc?rev=1395211&view=rev
Log:
TOMAHAWK-1639 AbstractHtmlDataTable.expandAllDetails() doesn't work unless rowKey is specified on dataTable 

Added:
    myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/component/html/ext/DetailTogglerModel.java   (with props)
Modified:
    myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/component/html/ext/AbstractHtmlDataTable.java
    myfaces/tomahawk/trunk/core20/src/test/java/org/apache/myfaces/component/html/ext/HtmlDataTableTest.java

Modified: myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/component/html/ext/AbstractHtmlDataTable.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/component/html/ext/AbstractHtmlDataTable.java?rev=1395211&r1=1395210&r2=1395211&view=diff
==============================================================================
--- myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/component/html/ext/AbstractHtmlDataTable.java (original)
+++ myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/component/html/ext/AbstractHtmlDataTable.java Sun Oct  7 04:37:18 2012
@@ -85,7 +85,8 @@ import org.apache.myfaces.shared_tomahaw
    clazz = "org.apache.myfaces.component.html.ext.HtmlDataTable",
    tagClass = "org.apache.myfaces.generated.taglib.html.ext.HtmlDataTableTag",
    tagHandler = "org.apache.myfaces.component.html.ext.HtmlDataTableTagHandler")
-public abstract class AbstractHtmlDataTable extends HtmlDataTableHack implements UserRoleAware, NewspaperTable
+public abstract class AbstractHtmlDataTable extends HtmlDataTableHack 
+    implements UserRoleAware, NewspaperTable, DetailTogglerModel
 {
     private static final Log log = LogFactory.getLog(AbstractHtmlDataTable.class);
 
@@ -121,8 +122,6 @@ public abstract class AbstractHtmlDataTa
 
     private boolean _isValidChildren = true;
 
-    private Map<String, Boolean> _expandedNodes = new HashMap<String, Boolean>();
-
     //private Map<String, Object> _detailRowStates = new HashMap<String, Object>();
 
     private TableContext _tableContext = null;
@@ -145,7 +144,7 @@ public abstract class AbstractHtmlDataTa
      * This facet renders an additional row after or before (according
      * to detailStampLocation value) the current row, usually containing
      * additional information of the related row. It is toggled usually
-     * using varDetailToggle variable and the method toggleDetail().
+     * using varDetailToggler variable and the method toggleDetail().
      * 
      * @JSFFacet name="detailStamp"
      */
@@ -1543,7 +1542,7 @@ public abstract class AbstractHtmlDataTa
                 return null;
             }
             
-            Object[] values = new Object[5];
+            Object[] values = new Object[4];
             values[0] = parentSaved;
             
             if (isPreserveDataModel())
@@ -1558,12 +1557,11 @@ public abstract class AbstractHtmlDataTa
             
             values[2] = preserveSort ? getSortColumn() : null;
             values[3] = preserveSort ? Boolean.valueOf(isSortAscending()) : null;
-            values[4] = _expandedNodes;
             return values;
         }
         else
         {
-            Object[] values = new Object[5];
+            Object[] values = new Object[4];
             values[0] = super.saveState(context);
 
             if (isPreserveDataModel())
@@ -1578,7 +1576,6 @@ public abstract class AbstractHtmlDataTa
             
             values[2] = preserveSort ? getSortColumn() : null;
             values[3] = preserveSort ? Boolean.valueOf(isSortAscending()) : null;
-            values[4] = _expandedNodes;
 
             return values;
         }
@@ -1685,7 +1682,7 @@ public abstract class AbstractHtmlDataTa
             }
         }
 
-        _expandedNodes = (Map) values[4];
+        //_expandedNodes = (Map) values[4];
     }
 
     public _SerializableDataModel getSerializableDataModel()
@@ -1899,6 +1896,8 @@ public abstract class AbstractHtmlDataTa
      */
     @JSFProperty(defaultValue="false")
     public abstract boolean isDetailStampExpandedDefault();
+    
+    public abstract void setDetailStampExpandedDefault(boolean value);
 
     /**
      * before|after - where to render the detailStamp, before the 
@@ -2015,10 +2014,41 @@ public abstract class AbstractHtmlDataTa
         _preservedDataModel = preservedDataModel;
     }
 
+    protected Map<String, Object> getExpandedNodes()
+    {
+        return (Map<String, Object>) getStateHelper().get(PropertyKeys.expandedNodes);
+    }
+    
+    protected void clearExpandedNodes()
+    {
+        Map<String, Object> nodes = (Map<String, Object>) getExpandedNodes();
+        if (nodes != null)
+        {
+            nodes.clear();
+        }
+    }
+    
+    protected Boolean getExpandedNode(String key)
+    {
+        Map<String, Object> nodes = (Map<String, Object>) getExpandedNodes();
+        return (Boolean) ( (nodes == null) ? null : nodes.get(key) );
+    }
+    
+    protected Boolean setExpandedNode(String key, Boolean value)
+    {
+        return (Boolean) getStateHelper().put(PropertyKeys.expandedNodes, key, value);
+    }
+    
+    protected Boolean removeExpandedNode(String key)
+    {
+        return (Boolean) getStateHelper().remove(PropertyKeys.expandedNodes, key);
+    }
 
     public boolean isCurrentDetailExpanded()
     {
-        Boolean expanded = (Boolean) _expandedNodes.get(getContainerClientId(getFacesContext()));
+        Boolean expanded = (getValueExpression("rowKey") != null) ?
+                (Boolean) getExpandedNode(getContainerClientId(getFacesContext())) :
+                (Boolean) getExpandedNode(new Integer(getRowIndex()).toString());
         if (expanded != null)
         {
             return expanded.booleanValue();
@@ -2084,7 +2114,8 @@ public abstract class AbstractHtmlDataTa
      */
     public void toggleDetail()
     {
-        String derivedRowKey = getContainerClientId(getFacesContext());
+        String derivedRowKey = (getValueExpression("rowKey") != null) ?
+                getContainerClientId(getFacesContext()) : new Integer(getRowIndex()).toString();
 
         // get the current expanded state of the row
         boolean expanded = isDetailExpanded();
@@ -2095,12 +2126,12 @@ public abstract class AbstractHtmlDataTa
             if (isDetailStampExpandedDefault())
             {
                 // if default is expanded we have to override with FALSE here
-                _expandedNodes.put(derivedRowKey, Boolean.FALSE);
+                setExpandedNode(derivedRowKey, Boolean.FALSE);
             }
             else
             {
                 // if default is collapsed we can fallback to this default
-                _expandedNodes.remove(derivedRowKey);
+                removeExpandedNode(derivedRowKey);
             }
         }
         else
@@ -2110,12 +2141,12 @@ public abstract class AbstractHtmlDataTa
             if (isDetailStampExpandedDefault())
             {
                 // if default is expanded we can fallback to this default
-                _expandedNodes.remove(derivedRowKey);
+                removeExpandedNode(derivedRowKey);
             }
             else
             {
                 // if default is collapsed we have to override with TRUE
-                _expandedNodes.put(derivedRowKey, Boolean.TRUE);
+                setExpandedNode(derivedRowKey, Boolean.TRUE);
             }
         }
     }
@@ -2127,7 +2158,9 @@ public abstract class AbstractHtmlDataTa
      */
     public boolean isDetailExpanded()
     {
-        Boolean expanded = (Boolean) _expandedNodes.get(getContainerClientId(getFacesContext()));
+        Boolean expanded = (getValueExpression("rowKey") != null) ?
+                getExpandedNode(getContainerClientId(getFacesContext())) :
+                getExpandedNode(new Integer(getRowIndex()).toString());
         if (expanded == null)
         {
             return isDetailStampExpandedDefault();
@@ -2192,31 +2225,51 @@ public abstract class AbstractHtmlDataTa
      */
     public void expandAllDetails()
     {
-        int rowCount = getRowCount();
+        clearExpandedNodes();
 
-        _expandedNodes.clear();
-        
-        if (getRowKey() != null)
+        if (!isDetailStampExpandedDefault())
         {
+            setDetailStampExpandedDefault(true);
+        }
+    }
+    
+    public void expandAllPageDetails()
+    {
+        clearExpandedNodes();
+
+        if (!isDetailStampExpandedDefault())
+        {
+            // iterate over the rows
+            int rowsToProcess = getRows();
+            // if getRows() returns 0, all rows have to be processed
+            if (rowsToProcess == 0)
+            {
+                rowsToProcess = getRowCount();
+            }
+            int rowIndex = getFirst();
             int oldRow = getRowIndex();
+            boolean hasRowKey = getValueExpression("rowKey") != null;
             try
             {
-                for (int row = 0; row < rowCount; row++)
+                for (int rowsProcessed = 0; rowsProcessed < rowsToProcess; rowsProcessed++, rowIndex++)
                 {
-                    setRowIndex(row);
-                    _expandedNodes.put(getContainerClientId(getFacesContext()), Boolean.TRUE);
+                    if (hasRowKey)
+                    {
+                        setRowIndex(rowIndex);
+                        setExpandedNode(getContainerClientId(getFacesContext()), Boolean.TRUE);
+                    }
+                    else
+                    {
+                        setExpandedNode(new Integer(rowIndex).toString(), Boolean.TRUE);
+                    }
                 }
             }
             finally
             {
-                setRowIndex(oldRow);
-            }
-        }
-        else
-        {
-            for (int row = 0; row < rowCount; row++)
-            {
-                _expandedNodes.put(new Integer(row).toString(), Boolean.TRUE);
+                if (hasRowKey)
+                {
+                    setRowIndex(oldRow);
+                }
             }
         }
     }
@@ -2226,7 +2279,53 @@ public abstract class AbstractHtmlDataTa
      */
     public void collapseAllDetails()
     {
-        _expandedNodes.clear();
+        clearExpandedNodes();
+        
+        if (isDetailStampExpandedDefault())
+        {
+            setDetailStampExpandedDefault(false);
+        }
+    }
+    
+    public void collapseAllPageDetails()
+    {
+        clearExpandedNodes();
+        
+        if (isDetailStampExpandedDefault())
+        {
+            // iterate over the rows
+            int rowsToProcess = getRows();
+            // if getRows() returns 0, all rows have to be processed
+            if (rowsToProcess == 0)
+            {
+                rowsToProcess = getRowCount();
+            }
+            int rowIndex = getFirst();
+            int oldRow = getRowIndex();
+            boolean hasRowKey = getValueExpression("rowKey") != null;
+            try
+            {
+                for (int rowsProcessed = 0; rowsProcessed < rowsToProcess; rowsProcessed++, rowIndex++)
+                {
+                    if (hasRowKey)
+                    {
+                        setRowIndex(rowIndex);
+                        setExpandedNode(getContainerClientId(getFacesContext()), Boolean.FALSE);
+                    }
+                    else
+                    {
+                        setExpandedNode(new Integer(rowIndex).toString(), Boolean.FALSE);
+                    }
+                }
+            }
+            finally
+            {
+                if (hasRowKey)
+                {
+                    setRowIndex(oldRow);
+                }
+            }
+        }
     }
 
     /**
@@ -2235,9 +2334,9 @@ public abstract class AbstractHtmlDataTa
     public boolean isExpandedEmpty()
     {
         boolean expandedEmpty = true;
-        if (_expandedNodes != null)
+        if (getExpandedNodes() != null)
         {
-            expandedEmpty = _expandedNodes.isEmpty();
+            expandedEmpty = getExpandedNodes().isEmpty();
         }
         return expandedEmpty;
     }
@@ -2251,10 +2350,7 @@ public abstract class AbstractHtmlDataTa
     {
         if (expandedEmpty)
         {
-            if (_expandedNodes != null)
-            {
-                _expandedNodes.clear();
-            }
+            clearExpandedNodes();
         }
     }
 

Added: myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/component/html/ext/DetailTogglerModel.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/component/html/ext/DetailTogglerModel.java?rev=1395211&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/component/html/ext/DetailTogglerModel.java (added)
+++ myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/component/html/ext/DetailTogglerModel.java Sun Oct  7 04:37:18 2012
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.component.html.ext;
+
+/**
+ * This interface define a contract to manipulate the toggle state of components
+ * like t:dataTable with detailStamp enabled. An object implementing this interface
+ * is set on request scope under the key defined by varDetailToggler.
+ * 
+ * @author Leonardo Uribe
+ */
+public interface DetailTogglerModel
+{
+    /**
+     * Collapse all details of all rows in all pages.
+     */
+    public void collapseAllDetails();
+
+    /**
+     * Expand all details of the rows displayed on the current page.
+     */
+    public void collapseAllPageDetails();
+    
+    /**
+     * Expand all details of all rows in all pages.
+     */
+    public void expandAllDetails();
+    
+    /**
+     * Expand all details of the rows displayed on the current page.
+     */
+    public void expandAllPageDetails();
+    
+    /**
+     * Return true if the current detail row is expanded.
+     *
+     * @return true if the current detail row is expanded.
+     */
+    public boolean isCurrentDetailExpanded();
+
+    /**
+     * Change the status of the current detail row from collapsed to expanded or
+     * viceversa.
+     */
+    public void toggleDetail();
+    
+    /**
+     * true|false - true if the detailStamp should be expanded by default. default: false
+     * 
+     */
+    public boolean isDetailStampExpandedDefault();
+    
+}

Propchange: myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/component/html/ext/DetailTogglerModel.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: myfaces/tomahawk/trunk/core20/src/test/java/org/apache/myfaces/component/html/ext/HtmlDataTableTest.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core20/src/test/java/org/apache/myfaces/component/html/ext/HtmlDataTableTest.java?rev=1395211&r1=1395210&r2=1395211&view=diff
==============================================================================
--- myfaces/tomahawk/trunk/core20/src/test/java/org/apache/myfaces/component/html/ext/HtmlDataTableTest.java (original)
+++ myfaces/tomahawk/trunk/core20/src/test/java/org/apache/myfaces/component/html/ext/HtmlDataTableTest.java Sun Oct  7 04:37:18 2012
@@ -36,7 +36,6 @@ import javax.faces.context.FacesContext;
 import javax.faces.el.ValueBinding;
 import javax.faces.model.ListDataModel;
 
-import junit.framework.Test;
 
 import org.apache.myfaces.component.html.ext.HtmlDataTablePreserveRowComponentStateTest.RowData;
 import org.apache.myfaces.test.AbstractTomahawkViewControllerTestCase;
@@ -348,5 +347,184 @@ public class HtmlDataTableTest extends A
             assertEquals(model.get(i).getText(), detailStampText.getValue());
         }
     }
+    
+    public void testDetailStampRowState3() throws Exception
+    {
+        List<RowData> model = new ArrayList<RowData>();
+        model.add(new RowData("text1","style1"));
+        model.add(new RowData("text1","style2"));
+        model.add(new RowData("text1","style3"));
+        model.add(new RowData("text1","style4"));
+        
+        //Put on request map to be resolved later
+        request.setAttribute("list", model);
+        
+        UIViewRoot root = facesContext.getViewRoot();
+        HtmlDataTable table = new HtmlDataTable();
+        UIColumn column = new UIColumn();
+        UIPanel detailStampPanel = new UIPanel();
+        UIOutput text = new UIOutput();
+        UIOutput detailStampText = new UIOutput();
+        
+        //This is only required if markInitiaState fix is not used 
+        root.setId("root");
+        table.setId("table");
+        detailStampPanel.setId("detailStamp");
+        column.setId("column");
+        text.setId("text");
+        detailStampText.setId("detailStampText");
+        
+        table.setVar("row");
+        table.setPreserveRowComponentState(true);
+        table.setValueExpression("value", application.
+                getExpressionFactory().createValueExpression(
+                        facesContext.getELContext(),"#{list}",List.class));
+        
+        text.setValueExpression("value", application.
+                getExpressionFactory().createValueExpression(
+                        facesContext.getELContext(),"#{row.text}",String.class));
+
+        detailStampText.setValueExpression("value", application.
+                getExpressionFactory().createValueExpression(
+                        facesContext.getELContext(),"#{row.text}",String.class));
+        
+        root.getChildren().add(table);
+        table.getChildren().add(column);
+        table.getFacets().put(AbstractHtmlDataTable.DETAIL_STAMP_FACET_NAME, detailStampPanel);
+        column.getChildren().add(text);
+        detailStampPanel.getChildren().add(detailStampText);
+
+        //Check the value expressions are working and change the component state 
+        for (int i = 0; i < model.size(); i++)
+        {
+            RowData rowData = model.get(i); 
+            table.setRowIndex(i);
+            assertEquals(rowData.getText(), text.getValue());
+            assertEquals(rowData.getText(), detailStampText.getValue());
+        }
+        
+        //Reset row index
+        table.setRowIndex(-1);
+
+        //Remove a row
+        table.deleteRowStateForRow(1);
+        model.remove(1);
 
+        //Check the values were not lost
+        for (int i = 0; i < model.size(); i++)
+        {
+            table.setRowIndex(i);
+            assertEquals(model.get(i).getText(), text.getValue());
+            assertEquals(model.get(i).getText(), detailStampText.getValue());
+        }
+        
+        table.expandAllDetails();
+        
+        for (int i = 0; i < model.size(); i++)
+        {
+            table.setRowIndex(i);
+            assertTrue(table.isDetailExpanded());
+        }
+        
+        table.collapseAllDetails();
+        for (int i = 0; i < model.size(); i++)
+        {
+            table.setRowIndex(i);
+            assertFalse(table.isDetailExpanded());
+        }        
+    }
+    
+    public void testDetailStampRowState4() throws Exception
+    {
+        List<RowData> model = new ArrayList<RowData>();
+        model.add(new RowData("text1","style1"));
+        model.add(new RowData("text1","style2"));
+        model.add(new RowData("text1","style3"));
+        model.add(new RowData("text1","style4"));
+        
+        //Put on request map to be resolved later
+        request.setAttribute("list", model);
+        
+        UIViewRoot root = facesContext.getViewRoot();
+        HtmlDataTable table = new HtmlDataTable();
+        UIColumn column = new UIColumn();
+        UIPanel detailStampPanel = new UIPanel();
+        UIOutput text = new UIOutput();
+        UIOutput detailStampText = new UIOutput();
+        
+        //This is only required if markInitiaState fix is not used 
+        root.setId("root");
+        table.setId("table");
+        detailStampPanel.setId("detailStamp");
+        column.setId("column");
+        text.setId("text");
+        detailStampText.setId("detailStampText");
+        
+        table.setVar("row");
+        table.setPreserveRowComponentState(true);
+        table.setValueExpression("value", application.
+                getExpressionFactory().createValueExpression(
+                        facesContext.getELContext(),"#{list}",List.class));
+        table.setRows(2);
+        
+        text.setValueExpression("value", application.
+                getExpressionFactory().createValueExpression(
+                        facesContext.getELContext(),"#{row.text}",String.class));
+
+        detailStampText.setValueExpression("value", application.
+                getExpressionFactory().createValueExpression(
+                        facesContext.getELContext(),"#{row.text}",String.class));
+        
+        root.getChildren().add(table);
+        table.getChildren().add(column);
+        table.getFacets().put(AbstractHtmlDataTable.DETAIL_STAMP_FACET_NAME, detailStampPanel);
+        column.getChildren().add(text);
+        detailStampPanel.getChildren().add(detailStampText);
+
+        //Check the value expressions are working and change the component state 
+        for (int i = 0; i < model.size(); i++)
+        {
+            RowData rowData = model.get(i); 
+            table.setRowIndex(i);
+            assertEquals(rowData.getText(), text.getValue());
+            assertEquals(rowData.getText(), detailStampText.getValue());
+        }
+        
+        //Reset row index
+        table.setRowIndex(-1);
+
+        //Remove a row
+        table.deleteRowStateForRow(1);
+        model.remove(1);
+
+        //Check the values were not lost
+        for (int i = 0; i < model.size(); i++)
+        {
+            table.setRowIndex(i);
+            assertEquals(model.get(i).getText(), text.getValue());
+            assertEquals(model.get(i).getText(), detailStampText.getValue());
+        }
+        
+        table.expandAllPageDetails();
+        
+        for (int i = 0; i < model.size(); i++)
+        {
+            table.setRowIndex(i);
+            if (i < 2)
+            {
+                assertTrue(table.isDetailExpanded());
+            }
+            else
+            {
+                assertFalse(table.isDetailExpanded());
+            }
+        }
+        
+        table.collapseAllPageDetails();
+        for (int i = 0; i < model.size(); i++)
+        {
+            table.setRowIndex(i);
+            assertFalse(table.isDetailExpanded());
+        }        
+    }
 }