diff options
author | Johannes Dahlström <johannesd@vaadin.com> | 2013-01-23 13:14:18 +0200 |
---|---|---|
committer | Johannes Dahlström <johannesd@vaadin.com> | 2013-02-14 15:15:11 +0200 |
commit | 7a111fc541dcc507032cdad6799b477df6d4833f (patch) | |
tree | 426d7a0e7f971562cd5c0be265ae374dcca74802 /client | |
parent | 12996f599cf5284b4c2994764e26e700011e1a64 (diff) | |
download | vaadin-framework-7a111fc541dcc507032cdad6799b477df6d4833f.tar.gz vaadin-framework-7a111fc541dcc507032cdad6799b477df6d4833f.zip |
Merge of (#6160) and (#10470) to Vaadin 7.
Cache handling update.
Change-Id: I81ba74d457eb484f6f2c350629534ab284ead7b7
Diffstat (limited to 'client')
-rw-r--r-- | client/src/com/vaadin/client/ui/VScrollTable.java | 216 | ||||
-rw-r--r-- | client/src/com/vaadin/client/ui/table/TableConnector.java | 7 |
2 files changed, 169 insertions, 54 deletions
diff --git a/client/src/com/vaadin/client/ui/VScrollTable.java b/client/src/com/vaadin/client/ui/VScrollTable.java index 8553398718..75f5550790 100644 --- a/client/src/com/vaadin/client/ui/VScrollTable.java +++ b/client/src/com/vaadin/client/ui/VScrollTable.java @@ -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); } } diff --git a/client/src/com/vaadin/client/ui/table/TableConnector.java b/client/src/com/vaadin/client/ui/table/TableConnector.java index dedcab84fa..c967642059 100644 --- a/client/src/com/vaadin/client/ui/table/TableConnector.java +++ b/client/src/com/vaadin/client/ui/table/TableConnector.java @@ -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 |