]> source.dussan.org Git - vaadin-framework.git/commitdiff
Merge of (#6160) and (#10470) to Vaadin 7.
authorJohannes Dahlström <johannesd@vaadin.com>
Wed, 23 Jan 2013 11:14:18 +0000 (13:14 +0200)
committerJohannes Dahlström <johannesd@vaadin.com>
Thu, 14 Feb 2013 13:15:11 +0000 (15:15 +0200)
Cache handling update.

Change-Id: I81ba74d457eb484f6f2c350629534ab284ead7b7

client/src/com/vaadin/client/ui/VScrollTable.java
client/src/com/vaadin/client/ui/table/TableConnector.java
server/src/com/vaadin/ui/Table.java
uitest/src/com/vaadin/tests/components/table/EmptyRowsWhenScrolling.java [new file with mode: 0644]
uitest/src/com/vaadin/tests/components/treetable/EmptyingTreeTableTest.html [new file with mode: 0644]
uitest/src/com/vaadin/tests/components/treetable/TreeTableCacheOnPartialUpdate.html
uitest/src/com/vaadin/tests/components/treetable/TreeTableCacheOnPartialUpdates.java
uitest/src/com/vaadin/tests/components/treetable/TreeTableInternalError.html [new file with mode: 0644]
uitest/src/com/vaadin/tests/components/treetable/TreeTableInternalError.java [new file with mode: 0644]

index 85533987183aab4ad19c4066a2a82de9e44e7cef..75f5550790d884d95993533d5ea958b84825168d 100644 (file)
@@ -539,6 +539,13 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
     public int serverCacheFirst = -1;
     public int serverCacheLast = -1;
 
+    /**
+     * In several cases TreeTable depends on the scrollBody.lastRendered being
+     * 'out of sync' while the update is being done. In those cases the sanity
+     * check must be performed afterwards.
+     */
+    public boolean postponeSanityCheckForLastRendered;
+
     /** For internal use only. May be removed or replaced in the future. */
     public boolean sizeNeedsInit = true;
 
@@ -1375,9 +1382,12 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
         if (uidl == null || reqRows < 1) {
             // container is empty, remove possibly existing rows
             if (firstRow <= 0) {
-                while (scrollBody.getLastRendered() > scrollBody.firstRendered) {
+                postponeSanityCheckForLastRendered = true;
+                while (scrollBody.getLastRendered() > scrollBody
+                        .getFirstRendered()) {
                     scrollBody.unlinkRow(false);
                 }
+                postponeSanityCheckForLastRendered = false;
                 scrollBody.unlinkRow(false);
             }
             return;
@@ -1408,6 +1418,13 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
                 * cache_rate);
         int lastRowToKeep = (int) (firstRowInViewPort + pageLength + pageLength
                 * cache_rate);
+        // sanity checks:
+        if (firstRowToKeep < 0) {
+            firstRowToKeep = 0;
+        }
+        if (lastRowToKeep > totalRows) {
+            lastRowToKeep = totalRows - 1;
+        }
         debug("Client side calculated cache rows to keep: " + firstRowToKeep
                 + "-" + lastRowToKeep);
 
@@ -1999,15 +2016,13 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
                 if (totalRows - 1 > scrollBody.getLastRendered()) {
                     // fetch cache rows
                     int firstInNewSet = scrollBody.getLastRendered() + 1;
-                    rowRequestHandler.setReqFirstRow(firstInNewSet);
                     int lastInNewSet = (int) (firstRowInViewPort + pageLength + cache_rate
                             * pageLength);
                     if (lastInNewSet > totalRows - 1) {
                         lastInNewSet = totalRows - 1;
                     }
-                    rowRequestHandler.setReqRows(lastInNewSet - firstInNewSet
-                            + 1);
-                    rowRequestHandler.deferRowFetch(1);
+                    rowRequestHandler.triggerRowFetch(firstInNewSet,
+                            lastInNewSet - firstInNewSet + 1, 1);
                 }
             }
         }
@@ -2093,6 +2108,18 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
         private int reqRows = 0;
         private boolean isRunning = false;
 
+        public void triggerRowFetch(int first, int rows) {
+            setReqFirstRow(first);
+            setReqRows(rows);
+            deferRowFetch();
+        }
+
+        public void triggerRowFetch(int first, int rows, int delay) {
+            setReqFirstRow(first);
+            setReqRows(rows);
+            deferRowFetch(delay);
+        }
+
         public void deferRowFetch() {
             deferRowFetch(250);
         }
@@ -2119,17 +2146,28 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
             }
         }
 
+        public int getReqFirstRow() {
+            return reqFirstRow;
+        }
+
         public void setReqFirstRow(int reqFirstRow) {
             if (reqFirstRow < 0) {
-                reqFirstRow = 0;
+                this.reqFirstRow = 0;
             } else if (reqFirstRow >= totalRows) {
-                reqFirstRow = totalRows - 1;
+                this.reqFirstRow = totalRows - 1;
+            } else {
+                this.reqFirstRow = reqFirstRow;
             }
-            this.reqFirstRow = reqFirstRow;
         }
 
         public void setReqRows(int reqRows) {
-            this.reqRows = reqRows;
+            if (reqRows < 0) {
+                this.reqRows = 0;
+            } else if (reqFirstRow + reqRows > totalRows) {
+                this.reqRows = totalRows - reqFirstRow;
+            } else {
+                this.reqRows = reqRows;
+            }
         }
 
         @Override
@@ -2140,7 +2178,15 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
                 schedule(250);
             } else {
 
-                int firstToBeRendered = scrollBody.firstRendered;
+                int firstRendered = scrollBody.getFirstRendered();
+                int lastRendered = scrollBody.getLastRendered();
+                if (lastRendered > totalRows) {
+                    lastRendered = totalRows - 1;
+                }
+                boolean rendered = firstRendered >= 0 && lastRendered >= 0;
+
+                int firstToBeRendered = firstRendered;
+
                 if (reqFirstRow < firstToBeRendered) {
                     firstToBeRendered = reqFirstRow;
                 } else if (firstRowInViewPort - (int) (cache_rate * pageLength) > firstToBeRendered) {
@@ -2149,12 +2195,24 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
                     if (firstToBeRendered < 0) {
                         firstToBeRendered = 0;
                     }
+                } else if (rendered && firstRendered + 1 < reqFirstRow
+                        && lastRendered + 1 < reqFirstRow) {
+                    // requested rows must fall within the requested rendering
+                    // area
+                    firstToBeRendered = reqFirstRow;
+                }
+                if (firstToBeRendered + reqRows < firstRendered) {
+                    // must increase the required row count accordingly,
+                    // otherwise may leave a gap and the rows beyond will get
+                    // removed
+                    setReqRows(firstRendered - firstToBeRendered);
                 }
 
-                int lastToBeRendered = scrollBody.lastRendered;
+                int lastToBeRendered = lastRendered;
+                int lastReqRow = reqFirstRow + reqRows - 1;
 
-                if (reqFirstRow + reqRows - 1 > lastToBeRendered) {
-                    lastToBeRendered = reqFirstRow + reqRows - 1;
+                if (lastReqRow > lastToBeRendered) {
+                    lastToBeRendered = lastReqRow;
                 } else if (firstRowInViewPort + pageLength + pageLength
                         * cache_rate < lastToBeRendered) {
                     lastToBeRendered = (firstRowInViewPort + pageLength + (int) (pageLength * cache_rate));
@@ -2163,14 +2221,36 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
                     }
                     // due Safari 3.1 bug (see #2607), verify reqrows, original
                     // problem unknown, but this should catch the issue
-                    if (reqFirstRow + reqRows - 1 > lastToBeRendered) {
-                        reqRows = lastToBeRendered - reqFirstRow;
+                    if (lastReqRow > lastToBeRendered) {
+                        setReqRows(lastToBeRendered - reqFirstRow);
                     }
+                } else if (rendered && lastRendered - 1 > lastReqRow
+                        && firstRendered - 1 > lastReqRow) {
+                    // requested rows must fall within the requested rendering
+                    // area
+                    lastToBeRendered = lastReqRow;
+                }
+
+                if (lastToBeRendered > totalRows) {
+                    lastToBeRendered = totalRows - 1;
+                }
+                if (reqFirstRow < firstToBeRendered
+                        || (reqFirstRow > firstToBeRendered && (reqFirstRow < firstRendered || reqFirstRow > lastRendered + 1))) {
+                    setReqFirstRow(firstToBeRendered);
+                }
+                if (lastRendered < lastToBeRendered
+                        && lastRendered + reqRows < lastToBeRendered) {
+                    // must increase the required row count accordingly,
+                    // otherwise may leave a gap and the rows after will get
+                    // removed
+                    setReqRows(lastToBeRendered - lastRendered);
+                } else if (lastToBeRendered >= firstRendered
+                        && reqFirstRow + reqRows < firstRendered) {
+                    setReqRows(lastToBeRendered - lastRendered);
                 }
 
                 client.updateVariable(paintableId, "firstToBeRendered",
                         firstToBeRendered, false);
-
                 client.updateVariable(paintableId, "lastToBeRendered",
                         lastToBeRendered, false);
                 // remember which firstvisible we requested, in case the server
@@ -2191,10 +2271,6 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
             }
         }
 
-        public int getReqFirstRow() {
-            return reqFirstRow;
-        }
-
         /**
          * Sends request to refresh content at this position.
          */
@@ -3991,6 +4067,24 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
             setElement(container);
         }
 
+        public void setLastRendered(int lastRendered) {
+            if (totalRows >= 0 && lastRendered > totalRows) {
+                VConsole.log("setLastRendered: " + this.lastRendered + " -> "
+                        + lastRendered);
+                this.lastRendered = totalRows - 1;
+            } else {
+                this.lastRendered = lastRendered;
+            }
+        }
+
+        public int getLastRendered() {
+            return lastRendered;
+        }
+
+        public int getFirstRendered() {
+            return firstRendered;
+        }
+
         public VScrollTableRow getRowByRowIndex(int indexInTable) {
             int internalIndex = indexInTable - firstRendered;
             if (internalIndex >= 0 && internalIndex < renderedRows.size()) {
@@ -4045,7 +4139,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
 
         public void renderInitialRows(UIDL rowData, int firstIndex, int rows) {
             firstRendered = firstIndex;
-            lastRendered = firstIndex + rows - 1;
+            setLastRendered(firstIndex + rows - 1);
             final Iterator<?> it = rowData.getChildIterator();
             aligns = tHead.getColumnAlignments();
             while (it.hasNext()) {
@@ -4065,7 +4159,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
                 while (it.hasNext()) {
                     final VScrollTableRow row = prepareRow((UIDL) it.next());
                     addRow(row);
-                    lastRendered++;
+                    setLastRendered(lastRendered + 1);
                 }
                 fixSpacers();
             } else if (firstIndex + rows == firstRendered) {
@@ -4081,19 +4175,27 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
                 }
             } else {
                 // completely new set of rows
+
+                // there can't be sanity checks for last rendered within this
+                // while loop regardless of what has been set previously, so
+                // change it temporarily to true and then return the original
+                // value
+                boolean temp = postponeSanityCheckForLastRendered;
+                postponeSanityCheckForLastRendered = true;
                 while (lastRendered + 1 > firstRendered) {
                     unlinkRow(false);
                 }
-                final VScrollTableRow row = prepareRow((UIDL) it.next());
+                postponeSanityCheckForLastRendered = temp;
+                VScrollTableRow row = prepareRow((UIDL) it.next());
                 firstRendered = firstIndex;
-                lastRendered = firstIndex - 1;
+                setLastRendered(firstIndex - 1);
                 addRow(row);
-                lastRendered++;
+                setLastRendered(lastRendered + 1);
                 setContainerHeight();
                 fixSpacers();
                 while (it.hasNext()) {
                     addRow(prepareRow((UIDL) it.next()));
-                    lastRendered++;
+                    setLastRendered(lastRendered + 1);
                 }
                 fixSpacers();
             }
@@ -4129,14 +4231,12 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
                  * not waste time rendering a set of rows that will never be
                  * visible...
                  */
-                rowRequestHandler.setReqFirstRow(reactFirstRow);
-                rowRequestHandler.setReqRows(reactLastRow - reactFirstRow + 1);
-                rowRequestHandler.deferRowFetch(1);
+                rowRequestHandler.triggerRowFetch(reactFirstRow, reactLastRow
+                        - reactFirstRow + 1, 1);
             } else if (lastRendered < reactLastRow) {
                 // get some cache rows below visible area
-                rowRequestHandler.setReqFirstRow(lastRendered + 1);
-                rowRequestHandler.setReqRows(reactLastRow - lastRendered);
-                rowRequestHandler.deferRowFetch(1);
+                rowRequestHandler.triggerRowFetch(lastRendered + 1,
+                        reactLastRow - lastRendered, 1);
             } else if (firstRendered > reactFirstRow) {
                 /*
                  * Branch for fetching cache above visible area.
@@ -4146,9 +4246,8 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
                  * some rare situations the table may make two cache visits to
                  * server.
                  */
-                rowRequestHandler.setReqFirstRow(reactFirstRow);
-                rowRequestHandler.setReqRows(firstRendered - reactFirstRow);
-                rowRequestHandler.deferRowFetch(1);
+                rowRequestHandler.triggerRowFetch(reactFirstRow, firstRendered
+                        - reactFirstRow, 1);
             }
         }
 
@@ -4172,7 +4271,11 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
                     final VScrollTableRow row = prepareRow((UIDL) it.next());
                     addRow(row);
                     insertedRows.add(row);
-                    lastRendered++;
+                    if (postponeSanityCheckForLastRendered) {
+                        lastRendered++;
+                    } else {
+                        setLastRendered(lastRendered + 1);
+                    }
                 }
                 fixSpacers();
             } else if (firstIndex + rows == firstRendered) {
@@ -4194,7 +4297,11 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
                     VScrollTableRow row = prepareRow((UIDL) it.next());
                     insertRowAt(row, ix);
                     insertedRows.add(row);
-                    lastRendered++;
+                    if (postponeSanityCheckForLastRendered) {
+                        lastRendered++;
+                    } else {
+                        setLastRendered(lastRendered + 1);
+                    }
                     ix++;
                 }
                 fixSpacers();
@@ -4307,7 +4414,11 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
                 firstRendered++;
             } else {
                 actualIx = renderedRows.size() - 1;
-                lastRendered--;
+                if (postponeSanityCheckForLastRendered) {
+                    --lastRendered;
+                } else {
+                    setLastRendered(lastRendered - 1);
+                }
             }
             if (actualIx >= 0) {
                 unlinkRowAtActualIndex(actualIx);
@@ -4323,6 +4434,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
             }
             if (firstRendered > firstIndex
                     && firstRendered < firstIndex + count) {
+                count = count - (firstRendered - firstIndex);
                 firstIndex = firstRendered;
             }
             int lastIndex = firstIndex + count - 1;
@@ -4331,7 +4443,12 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
             }
             for (int ix = lastIndex; ix >= firstIndex; ix--) {
                 unlinkRowAtActualIndex(actualIndex(ix));
-                lastRendered--;
+                if (postponeSanityCheckForLastRendered) {
+                    // partialUpdate handles sanity check later
+                    lastRendered--;
+                } else {
+                    setLastRendered(lastRendered - 1);
+                }
             }
             fixSpacers();
         }
@@ -4352,7 +4469,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
             }
             for (int ix = renderedRows.size() - 1; ix >= index; ix--) {
                 unlinkRowAtActualIndex(actualIndex(ix));
-                lastRendered--;
+                setLastRendered(lastRendered - 1);
             }
             fixSpacers();
         }
@@ -4538,14 +4655,6 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
             }
         }
 
-        public int getLastRendered() {
-            return lastRendered;
-        }
-
-        public int getFirstRendered() {
-            return firstRendered;
-        }
-
         public void moveCol(int oldIndex, int newIndex) {
 
             // loop all rows and move given index to its new place
@@ -5911,8 +6020,8 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
             client.updateVariable(paintableId, "pagelength", pageLength, false);
 
             if (!rendering) {
-                int currentlyVisible = scrollBody.lastRendered
-                        - scrollBody.firstRendered;
+                int currentlyVisible = scrollBody.getLastRendered()
+                        - scrollBody.getFirstRendered();
                 if (currentlyVisible < pageLength
                         && currentlyVisible < totalRows) {
                     // shake scrollpanel to fill empty space
@@ -6397,10 +6506,9 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
         }
         if (postLimit > lastRendered) {
             // need some rows to the end of the rendered area
-            rowRequestHandler.setReqFirstRow(lastRendered + 1);
-            rowRequestHandler.setReqRows((int) ((firstRowInViewPort
-                    + pageLength + pageLength * cache_rate) - lastRendered));
-            rowRequestHandler.deferRowFetch();
+            int reqRows = (int) ((firstRowInViewPort + pageLength + pageLength
+                    * cache_rate) - lastRendered);
+            rowRequestHandler.triggerRowFetch(lastRendered + 1, reqRows);
         }
     }
 
index dedcab84fa2f55ad0fe36203722536ce22fea70d..c967642059805303428413e119adc39ce30d7a3d 100644 (file)
@@ -165,12 +165,19 @@ public class TableConnector extends AbstractHasComponentsConnector implements
         UIDL partialRowAdditions = uidl.getChildByTagName("prows");
         UIDL partialRowUpdates = uidl.getChildByTagName("urows");
         if (partialRowUpdates != null || partialRowAdditions != null) {
+            getWidget().postponeSanityCheckForLastRendered = true;
             // we may have pending cache row fetch, cancel it. See #2136
             getWidget().rowRequestHandler.cancel();
 
             getWidget().updateRowsInBody(partialRowUpdates);
             getWidget().addAndRemoveRows(partialRowAdditions);
+
+            // sanity check (in case the value has slipped beyond the total
+            // amount of rows)
+            getWidget().scrollBody.setLastRendered(getWidget().scrollBody
+                    .getLastRendered());
         } else {
+            getWidget().postponeSanityCheckForLastRendered = false;
             UIDL rowData = uidl.getChildByTagName("rows");
             if (rowData != null) {
                 // we may have pending cache row fetch, cancel it. See #2136
index a9632da038753c250b7190ebec2bfb20e1552235..641c0ff1f63b1788a7301b386f19c739c593f70e 100644 (file)
@@ -1645,6 +1645,9 @@ public class Table extends AbstractSelect implements Action.Container,
         if (rows > 0) {
             pageBufferFirstIndex = firstIndex;
         }
+        if (getPageLength() != 0) {
+            removeUnnecessaryRows();
+        }
 
         setRowCacheInvalidated(true);
         markAsDirty();
@@ -1710,6 +1713,47 @@ public class Table extends AbstractSelect implements Action.Container,
 
     }
 
+    /**
+     * Removes rows that fall outside the required cache.
+     */
+    private void removeUnnecessaryRows() {
+        int minPageBufferIndex = getMinPageBufferIndex();
+        int maxPageBufferIndex = getMaxPageBufferIndex();
+
+        int maxBufferSize = maxPageBufferIndex - minPageBufferIndex + 1;
+
+        /*
+         * Number of rows that were previously cached. This is not necessarily
+         * the same as pageLength if we do not have enough rows in the
+         * container.
+         */
+        int currentlyCachedRowCount = pageBuffer[CELL_ITEMID].length;
+
+        if (currentlyCachedRowCount <= maxBufferSize) {
+            // removal unnecessary
+            return;
+        }
+
+        /* Figure out which rows to get rid of. */
+        int firstCacheRowToRemoveInPageBuffer = -1;
+        if (minPageBufferIndex > pageBufferFirstIndex) {
+            firstCacheRowToRemoveInPageBuffer = pageBufferFirstIndex;
+        } else if (maxPageBufferIndex < pageBufferFirstIndex
+                + currentlyCachedRowCount) {
+            firstCacheRowToRemoveInPageBuffer = maxPageBufferIndex + 1;
+        }
+
+        if (firstCacheRowToRemoveInPageBuffer - pageBufferFirstIndex < currentlyCachedRowCount) {
+            /*
+             * Unregister all components that fall beyond the cache limits after
+             * inserting the new rows.
+             */
+            unregisterComponentsAndPropertiesInRows(
+                    firstCacheRowToRemoveInPageBuffer, currentlyCachedRowCount
+                            - firstCacheRowToRemoveInPageBuffer);
+        }
+    }
+
     /**
      * Requests that the Table should be repainted as soon as possible.
      * 
@@ -1856,41 +1900,24 @@ public class Table extends AbstractSelect implements Action.Container,
                         "Insert {0} rows at index {1} to existing page buffer requested",
                         new Object[] { rows, firstIndex });
 
-        // Page buffer must not become larger than pageLength*cacheRate before
-        // or after the current page
-        int minPageBufferIndex = getCurrentPageFirstItemIndex()
-                - (int) (getPageLength() * getCacheRate());
-        if (minPageBufferIndex < 0) {
-            minPageBufferIndex = 0;
-        }
+        int minPageBufferIndex = getMinPageBufferIndex();
+        int maxPageBufferIndex = getMaxPageBufferIndex();
 
-        int maxPageBufferIndex = getCurrentPageFirstItemIndex()
-                + (int) (getPageLength() * (1 + getCacheRate()));
-        int maxBufferSize = maxPageBufferIndex - minPageBufferIndex;
+        int maxBufferSize = maxPageBufferIndex - minPageBufferIndex + 1;
 
         if (getPageLength() == 0) {
             // If pageLength == 0 then all rows should be rendered
-            maxBufferSize = pageBuffer[0].length + rows;
+            maxBufferSize = pageBuffer[CELL_ITEMID].length + rows;
         }
         /*
          * Number of rows that were previously cached. This is not necessarily
-         * the same as pageLength if we do not have enough rows in the
-         * container.
+         * the same as maxBufferSize.
          */
         int currentlyCachedRowCount = pageBuffer[CELL_ITEMID].length;
 
-        /*
-         * firstIndexInPageBuffer is the offset in pageBuffer where the new rows
-         * will be inserted (firstIndex is the index in the whole table).
-         * 
-         * E.g. scrolled down to row 1000: firstIndex==1010,
-         * pageBufferFirstIndex==1000 -> cacheIx==10
-         */
-        int firstIndexInPageBuffer = firstIndex - pageBufferFirstIndex;
-
         /* If rows > size available in page buffer */
-        if (firstIndexInPageBuffer + rows > maxBufferSize) {
-            rows = maxBufferSize - firstIndexInPageBuffer;
+        if (firstIndex + rows - 1 > maxPageBufferIndex) {
+            rows = maxPageBufferIndex - firstIndex + 1;
         }
 
         /*
@@ -1899,38 +1926,59 @@ public class Table extends AbstractSelect implements Action.Container,
          * the cache.
          */
 
-        /* All rows until the insertion point remain, always. */
-        int firstCacheRowToRemoveInPageBuffer = firstIndexInPageBuffer;
+        /*
+         * if there are rows before the new pageBuffer limits they must be
+         * removed
+         */
+        int lastCacheRowToRemove = minPageBufferIndex - 1;
+        int rowsFromBeginning = lastCacheRowToRemove - pageBufferFirstIndex + 1;
+        if (lastCacheRowToRemove >= pageBufferFirstIndex) {
+            unregisterComponentsAndPropertiesInRows(pageBufferFirstIndex,
+                    rowsFromBeginning);
+        } else {
+            rowsFromBeginning = 0;
+        }
 
+        /*
+         * the rows that fall outside of the new pageBuffer limits after the new
+         * rows are inserted must also be removed
+         */
+        int firstCacheRowToRemove = firstIndex;
         /*
          * IF there is space remaining in the buffer after the rows have been
          * inserted, we can keep more rows.
          */
-        int numberOfOldRowsAfterInsertedRows = maxBufferSize
-                - firstIndexInPageBuffer - rows;
+        int numberOfOldRowsAfterInsertedRows = Math.min(pageBufferFirstIndex
+                + currentlyCachedRowCount + rows, maxPageBufferIndex + 1)
+                - (firstIndex + rows - 1);
         if (numberOfOldRowsAfterInsertedRows > 0) {
-            firstCacheRowToRemoveInPageBuffer += numberOfOldRowsAfterInsertedRows;
+            firstCacheRowToRemove += numberOfOldRowsAfterInsertedRows;
         }
+        int rowsFromAfter = currentlyCachedRowCount
+                - (firstCacheRowToRemove - pageBufferFirstIndex);
 
-        if (firstCacheRowToRemoveInPageBuffer <= currentlyCachedRowCount) {
+        if (rowsFromAfter > 0) {
             /*
              * Unregister all components that fall beyond the cache limits after
              * inserting the new rows.
              */
-            unregisterComponentsAndPropertiesInRows(
-                    firstCacheRowToRemoveInPageBuffer + pageBufferFirstIndex,
-                    currentlyCachedRowCount - firstCacheRowToRemoveInPageBuffer
-                            + pageBufferFirstIndex);
+            unregisterComponentsAndPropertiesInRows(firstCacheRowToRemove,
+                    rowsFromAfter);
         }
 
         // Calculate the new cache size
-        int newCachedRowCount = currentlyCachedRowCount;
-        if (maxBufferSize == 0 || currentlyCachedRowCount < maxBufferSize) {
-            newCachedRowCount = currentlyCachedRowCount + rows;
-            if (maxBufferSize > 0 && newCachedRowCount > maxBufferSize) {
-                newCachedRowCount = maxBufferSize;
-            }
-        }
+        int newCachedRowCount = maxBufferSize;
+        if (pageBufferFirstIndex + currentlyCachedRowCount + rows - 1 < maxPageBufferIndex) {
+            // there aren't enough rows to fill the whole potential -> use what
+            // there is
+            newCachedRowCount -= maxPageBufferIndex
+                    - (pageBufferFirstIndex + currentlyCachedRowCount + rows - 1);
+        } else if (minPageBufferIndex < pageBufferFirstIndex) {
+            newCachedRowCount -= pageBufferFirstIndex - minPageBufferIndex;
+        }
+        /* calculate the internal location of the new rows within the new cache */
+        int firstIndexInNewPageBuffer = firstIndex - pageBufferFirstIndex
+                - rowsFromBeginning;
 
         /* Paint the new rows into a separate buffer */
         Object[][] cells = getVisibleCellsNoCache(firstIndex, rows, false);
@@ -1942,21 +1990,25 @@ public class Table extends AbstractSelect implements Action.Container,
         Object[][] newPageBuffer = new Object[pageBuffer.length][newCachedRowCount];
 
         for (int i = 0; i < pageBuffer.length; i++) {
-            for (int row = 0; row < firstIndexInPageBuffer; row++) {
+            for (int row = 0; row < firstIndexInNewPageBuffer; row++) {
                 // Copy the first rows
-                newPageBuffer[i][row] = pageBuffer[i][row];
+                newPageBuffer[i][row] = pageBuffer[i][rowsFromBeginning + row];
             }
-            for (int row = firstIndexInPageBuffer; row < firstIndexInPageBuffer
+            for (int row = firstIndexInNewPageBuffer; row < firstIndexInNewPageBuffer
                     + rows; row++) {
                 // Copy the newly created rows
-                newPageBuffer[i][row] = cells[i][row - firstIndexInPageBuffer];
+                newPageBuffer[i][row] = cells[i][row
+                        - firstIndexInNewPageBuffer];
             }
-            for (int row = firstIndexInPageBuffer + rows; row < newCachedRowCount; row++) {
+            for (int row = firstIndexInNewPageBuffer + rows; row < newCachedRowCount; row++) {
                 // Move the old rows down below the newly inserted rows
-                newPageBuffer[i][row] = pageBuffer[i][row - rows];
+                newPageBuffer[i][row] = pageBuffer[i][rowsFromBeginning + row
+                        - rows];
             }
         }
         pageBuffer = newPageBuffer;
+        pageBufferFirstIndex = Math.max(pageBufferFirstIndex
+                + rowsFromBeginning, minPageBufferIndex);
         if (getLogger().isLoggable(Level.FINEST)) {
             getLogger().log(
                     Level.FINEST,
@@ -1970,6 +2022,40 @@ public class Table extends AbstractSelect implements Action.Container,
         return cells;
     }
 
+    private int getMaxPageBufferIndex() {
+        int total = size();
+        if (getPageLength() == 0) {
+            // everything is shown at once, no caching
+            return total - 1;
+        }
+        // Page buffer must not become larger than pageLength*cacheRate after
+        // the current page
+        int maxPageBufferIndex = getCurrentPageFirstItemIndex()
+                + (int) (getPageLength() * (1 + getCacheRate()));
+        if (shouldHideNullSelectionItem()) {
+            --total;
+        }
+        if (maxPageBufferIndex >= total) {
+            maxPageBufferIndex = total - 1;
+        }
+        return maxPageBufferIndex;
+    }
+
+    private int getMinPageBufferIndex() {
+        if (getPageLength() == 0) {
+            // everything is shown at once, no caching
+            return 0;
+        }
+        // Page buffer must not become larger than pageLength*cacheRate before
+        // the current page
+        int minPageBufferIndex = getCurrentPageFirstItemIndex()
+                - (int) (getPageLength() * getCacheRate());
+        if (minPageBufferIndex < 0) {
+            minPageBufferIndex = 0;
+        }
+        return minPageBufferIndex;
+    }
+
     /**
      * Render rows with index "firstIndex" to "firstIndex+rows-1" to a new
      * buffer.
@@ -3076,26 +3162,23 @@ public class Table extends AbstractSelect implements Action.Container,
         // Rows
         if (isPartialRowUpdate() && painted && !target.isFullRepaint()) {
             paintPartialRowUpdate(target, actionSet);
-            /*
-             * Send the page buffer indexes to ensure that the client side stays
-             * in sync. Otherwise we _might_ have the situation where the client
-             * side discards too few or too many rows, causing out of sync
-             * issues.
-             * 
-             * This could probably be done for full repaints also to simplify
-             * the client side.
-             */
-            int pageBufferLastIndex = pageBufferFirstIndex
-                    + pageBuffer[CELL_ITEMID].length - 1;
-            target.addAttribute(TableConstants.ATTRIBUTE_PAGEBUFFER_FIRST,
-                    pageBufferFirstIndex);
-            target.addAttribute(TableConstants.ATTRIBUTE_PAGEBUFFER_LAST,
-                    pageBufferLastIndex);
         } else if (target.isFullRepaint() || isRowCacheInvalidated()) {
             paintRows(target, cells, actionSet);
             setRowCacheInvalidated(false);
         }
 
+        /*
+         * Send the page buffer indexes to ensure that the client side stays in
+         * sync. Otherwise we _might_ have the situation where the client side
+         * discards too few or too many rows, causing out of sync issues.
+         */
+        int pageBufferLastIndex = pageBufferFirstIndex
+                + pageBuffer[CELL_ITEMID].length - 1;
+        target.addAttribute(TableConstants.ATTRIBUTE_PAGEBUFFER_FIRST,
+                pageBufferFirstIndex);
+        target.addAttribute(TableConstants.ATTRIBUTE_PAGEBUFFER_LAST,
+                pageBufferLastIndex);
+
         paintSorting(target);
 
         resetVariablesAndPageBuffer(target);
diff --git a/uitest/src/com/vaadin/tests/components/table/EmptyRowsWhenScrolling.java b/uitest/src/com/vaadin/tests/components/table/EmptyRowsWhenScrolling.java
new file mode 100644 (file)
index 0000000..c1ae9b4
--- /dev/null
@@ -0,0 +1,275 @@
+package com.vaadin.tests.components.table;
+
+import java.util.Random;
+
+import com.vaadin.annotations.AutoGenerated;
+import com.vaadin.data.util.BeanContainer;
+import com.vaadin.event.ShortcutAction.KeyCode;
+import com.vaadin.server.ClassResource;
+import com.vaadin.server.Resource;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.ui.AbsoluteLayout;
+import com.vaadin.ui.Alignment;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.Button.ClickListener;
+import com.vaadin.ui.CustomComponent;
+import com.vaadin.ui.Embedded;
+import com.vaadin.ui.HorizontalLayout;
+import com.vaadin.ui.Notification;
+import com.vaadin.ui.Table;
+import com.vaadin.ui.Table.ColumnGenerator;
+import com.vaadin.ui.UI;
+import com.vaadin.ui.VerticalLayout;
+
+/**
+ * This test cannot be automated. http://dev.vaadin.com/ticket/6160, base code
+ * by user radosdesign.
+ * 
+ * The test fails if even occasionally empty rows appear in the table. A
+ * relatively good way to get them (before the fix) is to wait for the page to
+ * load, move the scrollbar down, press 'R' before the rows have time to be
+ * rendered, and then move the scrollbar up when no rows have been rendered yet.
+ * After this, when you scroll down slowly there may be empty rows. This doesn't
+ * happen always, and you may need to force the threads slower to get it to
+ * happen at all. On a slow 32-bit Windows 7 with Chrome version 22.0.1229.94 m
+ * (no GWT dev mode) this test has managed to reproduce the problem maybe nine
+ * times out of ten.
+ * 
+ * @author Anna Koskinen / Vaadin Oy
+ * 
+ */
+public class EmptyRowsWhenScrolling extends UI {
+
+    @Override
+    public void init(VaadinRequest request) {
+        getPage().setTitle("Simpletable Application");
+        AppView appView = new AppView(this);
+        setContent(appView);
+        addAction(new Button.ClickShortcut(appView.getBtnRefreshTable(),
+                KeyCode.R));
+    }
+
+    private class AppView extends CustomComponent {
+
+        @AutoGenerated
+        private AbsoluteLayout mainLayout;
+        @AutoGenerated
+        private VerticalLayout verticalLayout_1;
+        @AutoGenerated
+        private Table table;
+        @AutoGenerated
+        private HorizontalLayout horizontalLayout_1;
+        @AutoGenerated
+        private Button btnRefreshTable;
+
+        /*- VaadinEditorProperties={"grid":"RegularGrid,20","showGrid":true,"snapToGrid":true,"snapToObject":true,"movingGuides":false,"snappingDistance":10} */
+
+        /*- VaadinEditorProperties={"grid":"RegularGrid,20","showGrid":true,"snapToGrid":true,"snapToObject":true,"movingGuides":false,"snappingDistance":10} */
+
+        /**
+         * The constructor should first build the main layout, set the
+         * composition root and then do any custom initialization.
+         * 
+         * The constructor will not be automatically regenerated by the visual
+         * editor.
+         */
+        public AppView(final UI application) {
+            buildMainLayout();
+            setCompositionRoot(mainLayout);
+
+            // Container with sample data
+            BeanContainer<Integer, SimpleBean> container = new BeanContainer<Integer, SimpleBean>(
+                    SimpleBean.class);
+            container.setBeanIdProperty("id");
+            for (int i = 1; i <= 50; ++i) {
+                container.addBean(new SimpleBean(i, "image",
+                        "Column1 row " + i, "Column2 row " + i, "Column3 row "
+                                + i, "Column4 row " + i));
+            }
+            table.setContainerDataSource(container);
+            table.setEditable(true);
+            table.setColumnReorderingAllowed(true);
+            table.setVisibleColumns(new String[] { "image", "id", "col1",
+                    "col2", "col3", "col4" });
+            table.addGeneratedColumn("image", new ColumnGenerator() {
+                public Object generateCell(Table source, Object itemId,
+                        Object columnId) {
+                    int imgNum = new Random().nextInt(5) + 1;
+                    try {
+                        // Simulate background work
+                        System.out
+                                .println("Generated column for image /com/example/simpletable/img/px50-"
+                                        + imgNum + ".jpg");
+                        Thread.sleep(50);
+                    } catch (InterruptedException e) {
+                        e.printStackTrace();
+                    }
+                    Resource resource = new ClassResource(
+                            "/com/example/simpletable/img/px50-" + imgNum
+                                    + ".jpg");
+                    Embedded image = new Embedded("", resource);
+                    image.setWidth("50px");
+                    image.setHeight("50px");
+                    image.addClickListener(new com.vaadin.event.MouseEvents.ClickListener() {
+                        public void click(
+                                com.vaadin.event.MouseEvents.ClickEvent event) {
+                            Notification.show("Image clicked!");
+                        }
+                    });
+                    return image;
+                }
+            });
+
+            // Refresh table button
+            getBtnRefreshTable().addClickListener(new ClickListener() {
+                public void buttonClick(ClickEvent event) {
+                    table.refreshRowCache();
+                }
+            });
+        }
+
+        @AutoGenerated
+        private AbsoluteLayout buildMainLayout() {
+            // common part: create layout
+            mainLayout = new AbsoluteLayout();
+            mainLayout.setImmediate(false);
+            mainLayout.setWidth("100%");
+            mainLayout.setHeight("100%");
+
+            // top-level component properties
+            setWidth("100.0%");
+            setHeight("100.0%");
+
+            // verticalLayout_1
+            verticalLayout_1 = buildVerticalLayout_1();
+            mainLayout.addComponent(verticalLayout_1, "top:0.0px;left:0.0px;");
+
+            return mainLayout;
+        }
+
+        @AutoGenerated
+        private VerticalLayout buildVerticalLayout_1() {
+            // common part: create layout
+            verticalLayout_1 = new VerticalLayout();
+            verticalLayout_1.setImmediate(false);
+            verticalLayout_1.setWidth("100.0%");
+            verticalLayout_1.setHeight("100.0%");
+            verticalLayout_1.setMargin(false);
+
+            // horizontalLayout_1
+            horizontalLayout_1 = buildHorizontalLayout_1();
+            verticalLayout_1.addComponent(horizontalLayout_1);
+
+            // table_1
+            table = new Table();
+            table.setImmediate(false);
+            table.setWidth("100.0%");
+            table.setHeight("100.0%");
+            verticalLayout_1.addComponent(table);
+            verticalLayout_1.setExpandRatio(table, 1.0f);
+
+            return verticalLayout_1;
+        }
+
+        @AutoGenerated
+        private HorizontalLayout buildHorizontalLayout_1() {
+            // common part: create layout
+            horizontalLayout_1 = new HorizontalLayout();
+            horizontalLayout_1.setImmediate(false);
+            horizontalLayout_1.setWidth("100.0%");
+            horizontalLayout_1.setHeight("-1px");
+            horizontalLayout_1.setMargin(false);
+
+            // btnRefreshTable
+            setBtnRefreshTable(new Button());
+            getBtnRefreshTable().setCaption("Reload table row cache");
+            getBtnRefreshTable().setImmediate(false);
+            getBtnRefreshTable().setWidth("-1px");
+            getBtnRefreshTable().setHeight("-1px");
+            horizontalLayout_1.addComponent(getBtnRefreshTable());
+            horizontalLayout_1.setComponentAlignment(getBtnRefreshTable(),
+                    new Alignment(33));
+
+            return horizontalLayout_1;
+        }
+
+        public Button getBtnRefreshTable() {
+            return btnRefreshTable;
+        }
+
+        public void setBtnRefreshTable(Button btnRefreshTable) {
+            this.btnRefreshTable = btnRefreshTable;
+        }
+
+    }
+
+    protected class SimpleBean {
+        private int id;
+        private String image;
+        private String col1;
+        private String col2;
+        private String col3;
+        private String col4;
+
+        public SimpleBean(int id, String image, String col1, String col2,
+                String col3, String col4) {
+            super();
+            this.id = id;
+            this.image = image;
+            this.col1 = col1;
+            this.col2 = col2;
+            this.col3 = col3;
+            this.col4 = col4;
+        }
+
+        public String getImage() {
+            return image;
+        }
+
+        public void setImage(String image) {
+            this.image = image;
+        }
+
+        public String getCol1() {
+            return col1;
+        }
+
+        public void setCol1(String col1) {
+            this.col1 = col1;
+        }
+
+        public String getCol2() {
+            return col2;
+        }
+
+        public void setCol2(String col2) {
+            this.col2 = col2;
+        }
+
+        public String getCol3() {
+            return col3;
+        }
+
+        public void setCol3(String col3) {
+            this.col3 = col3;
+        }
+
+        public String getCol4() {
+            return col4;
+        }
+
+        public void setCol4(String col4) {
+            this.col4 = col4;
+        }
+
+        public int getId() {
+            return id;
+        }
+
+        public void setId(int id) {
+            this.id = id;
+        }
+    }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/treetable/EmptyingTreeTableTest.html b/uitest/src/com/vaadin/tests/components/treetable/EmptyingTreeTableTest.html
new file mode 100644 (file)
index 0000000..0c43d41
--- /dev/null
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="http://localhost:8888/run/com.vaadin.tests.components.treetable.TreeTableTest?restartApplication" />
+<title>EmptyingTreeTableTest</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">EmptyingTreeTableTest</td></tr>
+</thead><tbody>
+<tr>
+       <td>open</td>
+       <td>/run/com.vaadin.tests.components.treetable.TreeTableTest?restartApplication</td>
+       <td></td>
+</tr>
+<tr>
+       <td>screenCapture</td>
+       <td></td>
+       <td>initial</td>
+</tr>
+<tr>
+       <td>mouseClick</td>
+       <td>vaadin=runcomvaadintestscomponentstreetableTreeTableTest::PID_Smenu#item0</td>
+       <td>46,6</td>
+</tr>
+<tr>
+       <td>mouseClick</td>
+       <td>vaadin=runcomvaadintestscomponentstreetableTreeTableTest::Root/VOverlay[0]/VMenuBar[0]#item5</td>
+       <td>12,7</td>
+</tr>
+<tr>
+       <td>mouseClick</td>
+       <td>vaadin=runcomvaadintestscomponentstreetableTreeTableTest::Root/VOverlay[1]/VMenuBar[0]#item1</td>
+       <td>84,9</td>
+</tr>
+<tr>
+       <td>mouseClick</td>
+       <td>vaadin=runcomvaadintestscomponentstreetableTreeTableTest::Root/VOverlay[2]/VMenuBar[0]#item0</td>
+       <td>16,10</td>
+</tr>
+<tr>
+       <td>screenCapture</td>
+       <td></td>
+       <td>itemsRemoved</td>
+</tr>
+
+</tbody></table>
+</body>
+</html>
index d9366385ce612006f68c60c20fc7871bb205b570..df1656dd2339508c225a945cabe3f57b3aa53059 100644 (file)
@@ -4,12 +4,12 @@
 <head profile="http://selenium-ide.openqa.org/profiles/test-case">
 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
 <link rel="selenium.base" href="" />
-<title>New Test</title>
+<title>TreeTableCacheOnPartialUpdates</title>
 </head>
 <body>
 <table cellpadding="1" cellspacing="1" border="1">
 <thead>
-<tr><td rowspan="1" colspan="3">New Test</td></tr>
+<tr><td rowspan="1" colspan="3">TreeTableCacheOnPartialUpdates</td></tr>
 </thead><tbody>
 <tr>
        <td>open</td>
 </tr>
 <tr>
        <td>mouseClick</td>
-       <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[0]/VNativeButton[0]</td>
+       <td>cacheTestButton-1 (children)-A</td>
        <td>47,5</td>
 </tr>
 <tr>
        <td>mouseClick</td>
-       <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[1]/VNativeButton[0]</td>
+       <td>cacheTestButton-2-B</td>
        <td>46,7</td>
 </tr>
 <tr>
        <td>mouseClick</td>
-       <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[6]/VNativeButton[0]</td>
+       <td>cacheTestButton-7 (children)-G</td>
        <td>54,12</td>
 </tr>
 <tr>
@@ -48,7 +48,7 @@
 </tr>
 <tr>
        <td>mouseClick</td>
-       <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]</td>
+       <td>cacheTestButtonToggle-1 (children)-A</td>
        <td>10,7</td>
 </tr>
 <tr>
 </tr>
 <tr>
        <td>mouseClick</td>
-       <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[0]/VNativeButton[0]</td>
+       <td>cacheTestButton-1 (children)-A</td>
        <td>81,6</td>
 </tr>
 <tr>
        <td>mouseClick</td>
-       <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[1]/VNativeButton[0]</td>
+       <td>cacheTestButton-1.1-A.A</td>
        <td>73,8</td>
 </tr>
 <tr>
        <td>mouseClick</td>
-       <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[0]/VNativeButton[0]</td>
+       <td>cacheTestButton-1 (children)-A</td>
        <td>86,7</td>
 </tr>
 <tr>
        <td>mouseClick</td>
-       <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[5]/VNativeButton[0]</td>
+       <td>cacheTestButton-1.5-A.E</td>
        <td>72,2</td>
 </tr>
 <tr>
        <td>mouseClick</td>
-       <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[6]/VNativeButton[0]</td>
+       <td>cacheTestButton-2-B</td>
        <td>73,7</td>
 </tr>
 <tr>
 </tr>
 <tr>
        <td>mouseClick</td>
-       <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]</td>
+       <td>cacheTestButtonToggle-1 (children)-A</td>
        <td>11,2</td>
 </tr>
 <tr>
 </tr>
 <tr>
        <td>mouseClick</td>
-       <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[0]/VNativeButton[0]</td>
+       <td>cacheTestButton-1 (children)-A</td>
        <td>76,5</td>
 </tr>
 <tr>
        <td>mouseClick</td>
-       <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[2]/VNativeButton[0]</td>
+       <td>cacheTestButton-3 (children)-C</td>
        <td>58,7</td>
 </tr>
 <tr>
        <td>mouseClick</td>
-       <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[1]/VNativeButton[0]</td>
+       <td>cacheTestButton-2-B</td>
        <td>69,10</td>
 </tr>
 <tr>
        <td>mouseClick</td>
-       <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[0]/VNativeButton[0]</td>
+       <td>cacheTestButton-1 (children)-A</td>
        <td>78,7</td>
 </tr>
 <tr>
 </tr>
 <tr>
        <td>mouseClick</td>
-       <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[41]/VNativeButton[0]</td>
+       <td>cacheTestButton-100-CV</td>
        <td>53,-2462</td>
 </tr>
 <tr>
        <td>mouseClick</td>
-       <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[34]/VNativeButton[0]</td>
+       <td>cacheTestButton-93-CO</td>
        <td>91,-2452</td>
 </tr>
 <tr>
        <td>mouseClick</td>
-       <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[28]/VNativeButton[0]</td>
+       <td>cacheTestButton-87-CI</td>
        <td>84,-2461</td>
 </tr>
 <tr>
        <td>mouseClick</td>
-       <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[41]/VNativeButton[0]</td>
+       <td>cacheTestButton-100-CV</td>
        <td>102,-2452</td>
 </tr>
 <tr>
 </tr>
 <tr>
        <td>mouseClick</td>
-       <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[34]/domChild[0]/domChild[0]/domChild[0]</td>
+       <td>cacheTestButtonToggle-40 (children)-AN</td>
        <td>9,-995</td>
 </tr>
 <tr>
 </tr>
 <tr>
        <td>mouseClick</td>
-       <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[34]/VNativeButton[0]</td>
+       <td>cacheTestButton-40 (children)-AN</td>
        <td>93,-991</td>
 </tr>
 <tr>
 </tr>
 <tr>
        <td>mouseClick</td>
-       <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[35]/VNativeButton[0]</td>
+       <td>cacheTestButton-40.1-AN.A</td>
        <td>123,-991</td>
 </tr>
 <tr>
 </tr>
 <tr>
        <td>mouseClick</td>
-       <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[40]/VNativeButton[0]</td>
+       <td>cacheTestButton-40.6-AN.F</td>
        <td>114,-1000</td>
 </tr>
 <tr>
 </tr>
 <tr>
        <td>mouseClick</td>
-       <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[34]/VNativeButton[0]</td>
+       <td>cacheTestButton-40 (children)-AN</td>
        <td>118,-993</td>
 </tr>
 <tr>
 </tr>
 <tr>
        <td>mouseClick</td>
-       <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[34]/domChild[0]/domChild[0]/domChild[0]</td>
+       <td>cacheTestButtonToggle-40 (children)-AN</td>
        <td>9,-998</td>
 </tr>
 <tr>
 </tr>
 <tr>
        <td>mouseClick</td>
-       <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[34]/VNativeButton[0]</td>
+       <td>cacheTestButton-40 (children)-AN</td>
        <td>42,-990</td>
 </tr>
 <tr>
 </tr>
 <tr>
        <td>mouseClick</td>
-       <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[29]/VNativeButton[0]</td>
+       <td>cacheTestButton-35-AI</td>
        <td>84,-990</td>
 </tr>
 <tr>
 </tr>
 <tr>
        <td>waitForElementPresent</td>
-       <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[42]/VNativeButton[0]</td>
+       <td>cacheTestButton-48-AV</td>
        <td></td>
 </tr>
 <tr>
        <td>mouseClick</td>
-       <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[42]/VNativeButton[0]</td>
+       <td>cacheTestButton-48-AV</td>
        <td>98,-998</td>
 </tr>
 <tr>
 </tr>
 <tr>
        <td>mouseClick</td>
-       <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[35]/VNativeButton[0]</td>
+       <td>cacheTestButton-41-AO</td>
        <td>101,-994</td>
 </tr>
 <tr>
 </tr>
 <tr>
        <td>mouseClick</td>
-       <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[30]/VNativeButton[0]</td>
+       <td>cacheTestButton-86-CH</td>
        <td>136,-2447</td>
 </tr>
 <tr>
        <td>mouseClick</td>
-       <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[42]/VNativeButton[0]</td>
+       <td>cacheTestButton-98-CT</td>
        <td>131,-2462</td>
 </tr>
 <tr>
        <td>mouseClick</td>
-       <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[43]/VNativeButton[0]</td>
+       <td>cacheTestButton-99 (children)-CU</td>
        <td>134,-2459</td>
 </tr>
 <tr>
        <td>mouseClick</td>
-       <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[44]/VNativeButton[0]</td>
+       <td>cacheTestButton-100-CV</td>
        <td>144,-2454</td>
 </tr>
 <tr>
 </tr>
 <tr>
        <td>mouseClick</td>
-       <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[43]/domChild[0]/domChild[0]/domChild[0]</td>
+       <td>cacheTestButtonToggle-99 (children)-CU</td>
        <td>10,-2461</td>
 </tr>
 <tr>
        <td>waitForElementPresent</td>
-       <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[43]/VNativeButton[0]</td>
+       <td>cacheTestButton-99 (children)-CU</td>
        <td></td>
 </tr>
 <tr>
        <td>mouseClick</td>
-       <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[43]/VNativeButton[0]</td>
+       <td>cacheTestButton-99 (children)-CU</td>
        <td>65,-2456</td>
 </tr>
 <tr>
 </tr>
 <tr>
        <td>mouseClick</td>
-       <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[30]/VNativeButton[0]</td>
+       <td>cacheTestButton-86-CH</td>
        <td>109,-2455</td>
 </tr>
 <tr>
 </tr>
 <tr>
        <td>mouseClick</td>
-       <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[44]/VNativeButton[0]</td>
+       <td>cacheTestButton-99.1-CU.A</td>
        <td>82,-2457</td>
 </tr>
 <tr>
 </tr>
 <tr>
        <td>mouseClick</td>
-       <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[43]/VNativeButton[0]</td>
+       <td>cacheTestButton-99 (children)-CU</td>
        <td>85,-2792</td>
 </tr>
 <tr>
        <td>mouseClick</td>
-       <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[42]/VNativeButton[0]</td>
+       <td>cacheTestButton-98-CT</td>
        <td>101,-2788</td>
 </tr>
 <tr>
        <td>mouseClick</td>
-       <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[44]/VNativeButton[0]</td>
+       <td>cacheTestButton-99.1-CU.A</td>
        <td>111,-2794</td>
 </tr>
 <tr>
        <td>mouseClick</td>
-       <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[56]/VNativeButton[0]</td>
+       <td>cacheTestButton-99.13-CU.M</td>
        <td>113,-2794</td>
 </tr>
 <tr>
 <!--collapse 99-->
 <tr>
        <td>mouseClick</td>
-       <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[43]/domChild[0]/domChild[0]/domChild[0]</td>
+       <td>cacheTestButtonToggle-99 (children)-CU</td>
        <td>11,-2792</td>
 </tr>
 <tr>
 </tr>
 <tr>
        <td>waitForElementPresent</td>
-       <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[40]/VNativeButton[0]</td>
+       <td>cacheTestButton-99 (children)-CU</td>
        <td></td>
 </tr>
 <tr>
        <td>mouseClick</td>
-       <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[40]/VNativeButton[0]</td>
+       <td>cacheTestButton-99 (children)-CU</td>
        <td>71,-2465</td>
 </tr>
 <tr>
 </tr>
 <tr>
        <td>mouseClick</td>
-       <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[41]/VNativeButton[0]</td>
+       <td>cacheTestButton-100-CV</td>
        <td>81,-2459</td>
 </tr>
 <tr>
 </tr>
 <tr>
        <td>mouseClick</td>
-       <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[39]/VNativeButton[0]</td>
+       <td>cacheTestButton-98-CT</td>
        <td>80,-2458</td>
 </tr>
 <tr>
 </tr>
 <tr>
        <td>mouseClick</td>
-       <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[28]/VNativeButton[0]</td>
+       <td>cacheTestButton-87-CI</td>
        <td>86,-2462</td>
 </tr>
 <tr>
index c2bd3da8602a79667d7950e73c87f295e1710b3a..f792a32f8fb755518c7732e7ee64cf70c13bf052 100644 (file)
@@ -72,13 +72,11 @@ public class TreeTableCacheOnPartialUpdates extends TestBase {
         public Component generateCell(final com.vaadin.ui.Table source,
                 final Object itemId, Object columnId) {
             TestBean tb = (TestBean) itemId;
-            // if (!tb.getCol1().contains("children")) {
-            // return null;
-            // }
             String identifier = "Item " + itemId + "/" + columnId;
-            System.out.println("Generating new Button for " + identifier);
             Button btnCol3 = new NativeButton(identifier);
-            btnCol3.addListener(new Button.ClickListener() {
+            btnCol3.setId("cacheTestButton-" + tb.getCol1() + "-"
+                    + tb.getCol2());
+            btnCol3.addClickListener(new Button.ClickListener() {
                 @Override
                 public void buttonClick(ClickEvent event) {
                     log.log("Button " + event.getButton().getCaption()
@@ -91,6 +89,25 @@ public class TreeTableCacheOnPartialUpdates extends TestBase {
 
     }
 
+    public class Col4ColumnGenerator implements ColumnGenerator {
+        public Component generateCell(final com.vaadin.ui.Table source,
+                final Object itemId, Object columnId) {
+            TestBean tb = (TestBean) itemId;
+            String identifier = "Expand/Collapse";
+            Button btnCol4 = new NativeButton(identifier);
+            btnCol4.setId("cacheTestButtonToggle-" + tb.getCol1() + "-"
+                    + tb.getCol2());
+            btnCol4.addClickListener(new Button.ClickListener() {
+                public void buttonClick(ClickEvent event) {
+                    treeTable.setCollapsed(itemId,
+                            !treeTable.isCollapsed(itemId));
+                }
+            });
+            return btnCol4;
+        }
+
+    }
+
     protected int indexOfId(Table source, Object itemId) {
         Container.Ordered c = (Ordered) source.getContainerDataSource();
         if (c instanceof Container.Indexed) {
@@ -105,19 +122,17 @@ public class TreeTableCacheOnPartialUpdates extends TestBase {
     private TreeTable treeTable;
     private BeanItemContainer<TestBean> testBeanContainer;
     private static String[] columnHeaders = new String[] { "Col1", "Col2",
-            "Col3" };
+            "Col3", "Col4" };
     private static Object[] visibleColumns = new Object[] { "col1", "col2",
-            "col3" };
+            "col3", "col4" };
 
     @Override
     public void setup() {
-        setTheme("reindeer-tests");
-
         // Force row height to be the same in all browsers so scrolling based on
         // pixels works as expected
         Button b = new Button("Show first");
         addComponent(b);
-        b.addListener(new ClickListener() {
+        b.addClickListener(new ClickListener() {
 
             @Override
             public void buttonClick(ClickEvent event) {
@@ -132,7 +147,7 @@ public class TreeTableCacheOnPartialUpdates extends TestBase {
         cacheRateSelect.addItem(new Integer(1));
         cacheRateSelect.addItem(new Integer(2));
         cacheRateSelect.setValue(2);
-        cacheRateSelect.addListener(new ValueChangeListener() {
+        cacheRateSelect.addValueChangeListener(new ValueChangeListener() {
 
             @Override
             public void valueChange(ValueChangeEvent event) {
@@ -143,7 +158,6 @@ public class TreeTableCacheOnPartialUpdates extends TestBase {
         addComponent(cacheRateSelect);
         treeTable = new TreeTable();
         treeTable.addStyleName("table-equal-rowheight");
-        // treeTable.setPageLength(0);
         testBeanContainer = new BeanItemContainer<TestBean>(TestBean.class);
 
         Map<String, Integer> hasChildren = new HashMap<String, Integer>();
@@ -156,7 +170,8 @@ public class TreeTableCacheOnPartialUpdates extends TestBase {
         hasChildren.put("99", 20);
         treeTable.setContainerDataSource(createContainer(100, hasChildren));
         treeTable.addGeneratedColumn("col3", new Col3ColumnGenerator());
-        treeTable.addListener(new ExpandListener() {
+        treeTable.addGeneratedColumn("col4", new Col4ColumnGenerator());
+        treeTable.addExpandListener(new ExpandListener() {
 
             @Override
             public void nodeExpand(ExpandEvent event) {
@@ -164,7 +179,7 @@ public class TreeTableCacheOnPartialUpdates extends TestBase {
 
             }
         });
-        treeTable.addListener(new CollapseListener() {
+        treeTable.addCollapseListener(new CollapseListener() {
 
             @Override
             public void nodeCollapse(CollapseEvent event) {
@@ -172,12 +187,11 @@ public class TreeTableCacheOnPartialUpdates extends TestBase {
 
             }
         });
-        treeTable.setColumnHeaders(columnHeaders);
         treeTable.setVisibleColumns(visibleColumns);
+        treeTable.setColumnHeaders(columnHeaders);
         treeTable.setColumnWidth("col1", 150);
         treeTable.setColumnWidth("col2", 50);
         treeTable.setHeight("430px");
-        // treeTable.setColumnWidth("col3", 150);
         addComponent(log);
         addComponent(treeTable);
     }
diff --git a/uitest/src/com/vaadin/tests/components/treetable/TreeTableInternalError.html b/uitest/src/com/vaadin/tests/components/treetable/TreeTableInternalError.html
new file mode 100644 (file)
index 0000000..1aa952d
--- /dev/null
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="" />
+<title>TreeTableInternalError</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">TreeTableInternalError</td></tr>
+</thead><tbody>
+<tr>
+       <td>open</td>
+       <td>/run/com.vaadin.tests.components.treetable.TreeTableInternalError?restartApplication</td>
+       <td></td>
+</tr>
+<tr>
+       <td>scroll</td>
+       <td>vaadin=runcomvaadintestscomponentstreetableTreeTableInternalError::PID_Streetable/domChild[1]</td>
+       <td>1320</td>
+</tr>
+<tr>
+       <td>waitForElementPresent</td>
+       <td>cacheTestButtonToggle-57</td>
+       <td></td>
+</tr>
+<tr>
+       <td>click</td>
+       <td>resize</td>
+       <td></td>
+</tr>
+<tr>
+       <td>scroll</td>
+       <td>vaadin=runcomvaadintestscomponentstreetableTreeTableInternalError::PID_Streetable/domChild[1]</td>
+       <td>1500</td>
+</tr>
+<tr>
+       <td>waitForElementPresent</td>
+       <td>cacheTestButtonToggle-55</td>
+       <td></td>
+</tr>
+<tr>
+       <td>mouseClick</td>
+       <td>cacheTestButtonToggle-55</td>
+       <td>-402,-1632</td>
+</tr>
+<tr>
+       <td>mouseClick</td>
+       <td>cacheTestButtonToggle-58</td>
+       <td>-402,-1660</td>
+</tr>
+<tr>
+       <td>screenCapture</td>
+       <td></td>
+       <td></td>
+</tr>
+</tbody></table>
+</body>
+</html>
diff --git a/uitest/src/com/vaadin/tests/components/treetable/TreeTableInternalError.java b/uitest/src/com/vaadin/tests/components/treetable/TreeTableInternalError.java
new file mode 100644 (file)
index 0000000..f6d7f11
--- /dev/null
@@ -0,0 +1,82 @@
+package com.vaadin.tests.components.treetable;
+
+import com.vaadin.tests.components.TestBase;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.Component;
+import com.vaadin.ui.NativeButton;
+import com.vaadin.ui.Table.ColumnGenerator;
+import com.vaadin.ui.TreeTable;
+import com.vaadin.ui.VerticalLayout;
+
+public class TreeTableInternalError extends TestBase {
+    private TreeTable t;
+
+    @Override
+    protected void setup() {
+        VerticalLayout content = getLayout();
+        content.setSizeFull();
+
+        t = new TreeTable() {
+            {
+                setSizeFull();
+                fillTreeTable(this);
+            }
+        };
+        t.setId("treetable");
+        content.addComponent(t);
+        content.setExpandRatio(t, 1);
+
+        Button button = new Button("Resize") {
+            {
+                addClickListener(new Button.ClickListener() {
+                    public void buttonClick(ClickEvent event) {
+                        t.setHeight("300px");
+                    }
+                });
+            }
+        };
+        button.setId("resize");
+        content.addComponent(button);
+    }
+
+    @Override
+    protected String getDescription() {
+        return "Internal Error when scrolling down enough that more rows are loaded (cache updated), then scrolling down just a few rows and expanding rows";
+    }
+
+    @Override
+    protected Integer getTicketNumber() {
+        return 10057;
+    }
+
+    private void fillTreeTable(TreeTable t) {
+        t.addContainerProperty("name", String.class, null);
+        t.addGeneratedColumn("toggle", new ButtonColumnGenerator());
+        for (int i = 0; i < 1000; i++) {
+            t.addItem(i);
+            t.getContainerProperty(i, "name").setValue("Item-" + i);
+            t.addItem(i + "c");
+            t.getContainerProperty(i + "c", "name").setValue("Child-" + i);
+            t.setParent(i + "c", i);
+            t.setChildrenAllowed(i + "c", false);
+        }
+    }
+
+    public class ButtonColumnGenerator implements ColumnGenerator {
+        public Component generateCell(final com.vaadin.ui.Table source,
+                final Object itemId, Object columnId) {
+            String identifier = "Expand/Collapse";
+            Button btnCol = new NativeButton(identifier);
+            btnCol.setId("cacheTestButtonToggle-" + itemId);
+            btnCol.addClickListener(new Button.ClickListener() {
+                public void buttonClick(ClickEvent event) {
+                    t.setCollapsed(itemId, !t.isCollapsed(itemId));
+                }
+            });
+            return btnCol;
+        }
+
+    }
+
+}