summaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorArtur Signell <artur@vaadin.com>2013-02-15 21:05:57 +0200
committerArtur Signell <artur@vaadin.com>2013-02-15 21:06:28 +0200
commit4e8a6db5b2c70b73287af523b3eb1d29002eca77 (patch)
treed8dbacbb44d57ef0b0aebebf5966fbdd3ec4eb81 /server
parent2f69a0a0466a064c6303bc3b1d83ced42193a269 (diff)
parent46abcc10792d9e0ca3fa8ec2272c3bb2d1dde911 (diff)
downloadvaadin-framework-4e8a6db5b2c70b73287af523b3eb1d29002eca77.tar.gz
vaadin-framework-4e8a6db5b2c70b73287af523b3eb1d29002eca77.zip
Merge branch '7.0'
Change-Id: I3e0d66cd6bef2336004084e69a19c96d8346bf8d
Diffstat (limited to 'server')
-rw-r--r--server/src/com/vaadin/ui/Table.java207
1 files changed, 145 insertions, 62 deletions
diff --git a/server/src/com/vaadin/ui/Table.java b/server/src/com/vaadin/ui/Table.java
index a9632da038..641c0ff1f6 100644
--- a/server/src/com/vaadin/ui/Table.java
+++ b/server/src/com/vaadin/ui/Table.java
@@ -1645,6 +1645,9 @@ public class Table extends AbstractSelect implements Action.Container,
if (rows > 0) {
pageBufferFirstIndex = firstIndex;
}
+ if (getPageLength() != 0) {
+ removeUnnecessaryRows();
+ }
setRowCacheInvalidated(true);
markAsDirty();
@@ -1711,6 +1714,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.
*
* Note that a {@code Table} does not necessarily repaint its contents when
@@ -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);