summaryrefslogtreecommitdiffstats
path: root/client
diff options
context:
space:
mode:
authorJohannes Dahlström <johannesd@vaadin.com>2013-01-23 13:14:18 +0200
committerJohannes Dahlström <johannesd@vaadin.com>2013-02-14 15:15:11 +0200
commit7a111fc541dcc507032cdad6799b477df6d4833f (patch)
tree426d7a0e7f971562cd5c0be265ae374dcca74802 /client
parent12996f599cf5284b4c2994764e26e700011e1a64 (diff)
downloadvaadin-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.java216
-rw-r--r--client/src/com/vaadin/client/ui/table/TableConnector.java7
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