瀏覽代碼

Grid now supports bare ItemSetChangeEvents (#13334)

Change-Id: Id87b2d7f50720bbfd5011520ea0be32fead48635
tags/7.4.0.beta1
Henrik Paul 9 年之前
父節點
當前提交
8b22659b5b

+ 6
- 0
client/src/com/vaadin/client/data/AbstractRemoteDataSource.java 查看文件

@@ -550,4 +550,10 @@ public abstract class AbstractRemoteDataSource<T> implements DataSource<T> {
}
temporarilyPinnedRows = rows;
}

protected void resetDataAndSize(int newSize) {
dropFromCache(getCachedRange());
cached = Range.withLength(0, 0);
dataChangeHandler.resetDataAndSize(newSize);
}
}

+ 12
- 0
client/src/com/vaadin/client/data/DataChangeHandler.java 查看文件

@@ -67,4 +67,16 @@ public interface DataChangeHandler {
* the number of available rows
*/
public void dataAvailable(int firstRowIndex, int numberOfRows);

/**
* Resets all data and defines a new size for the data.
* <p>
* This should be used in the cases where the data has changed in some
* unverifiable way. I.e. "something happened". This will lead to a
* re-rendering of the current Grid viewport
*
* @param estimatedNewDataSize
* the estimated size of the new data set
*/
public void resetDataAndSize(int estimatedNewDataSize);
}

+ 5
- 0
client/src/com/vaadin/client/data/RpcDataSourceConnector.java 查看文件

@@ -142,6 +142,11 @@ public class RpcDataSourceConnector extends AbstractExtensionConnector {
public void insertRowData(int firstRow, int count) {
dataSource.insertRowData(firstRow, count);
}

@Override
public void resetDataAndSize(int size) {
dataSource.resetDataAndSize(size);
}
});
}


+ 22
- 0
client/src/com/vaadin/client/ui/grid/Grid.java 查看文件

@@ -1847,6 +1847,28 @@ public class Grid<T> extends ResizeComposite implements
numberOfItems);
fireEvent(new DataAvailableEvent(currentDataAvailable));
}

@Override
public void resetDataAndSize(int newSize) {
RowContainer body = escalator.getBody();

/*
* Because the data has simply changed and we don't really know
* what, we'll simply remove everything and redraw everything.
*/

double prevScroll = escalator.getScrollTop();
body.removeRows(0, body.getRowCount());
body.insertRows(0, newSize);

/*
* If data was removed or inserted above the scroll top, the
* scroll position is kept locked, leading to data
* "sliding under us". But we can't do anything about that,
* since simply _something_ happened.
*/
escalator.setScrollTop(prevScroll);
}
});

int previousRowCount = escalator.getBody().getRowCount();

+ 48
- 13
server/src/com/vaadin/data/RpcDataProviderExtension.java 查看文件

@@ -567,6 +567,8 @@ public class RpcDataProviderExtension extends AbstractExtension {

private final ActiveRowHandler activeRowHandler = new ActiveRowHandler();

private DataProviderRpc rpc;

private final ItemSetChangeListener itemListener = new ItemSetChangeListener() {
@Override
public void containerItemSetChange(ItemSetChangeEvent event) {
@@ -586,17 +588,49 @@ public class RpcDataProviderExtension extends AbstractExtension {
}

else {
Range visibleRows = activeRowHandler.activeRange;
List<?> itemIds = container.getItemIds(visibleRows.getStart(),
visibleRows.length());

keyMapper.removeActiveRows(keyMapper.activeRange);
keyMapper.addActiveRows(visibleRows, visibleRows.getStart(),
itemIds);
/*
* Clear everything we have in view, and let the client
* re-request for whatever it needs.
*
* Why this shortcut? Well, since anything could've happened, we
* don't know what has happened. There are a lot of use-cases we
* can cover at once with this carte blanche operation:
*
* 1) Grid is scrolled somewhere in the middle and all the
* rows-inview are removed. We need a new pageful.
*
* 2) Grid is scrolled somewhere in the middle and none of the
* visible rows are removed. We need no new rows.
*
* 3) Grid is scrolled all the way to the bottom, and the last
* rows are being removed. Grid needs to scroll up and request
* for more rows at the top.
*
* 4) Grid is scrolled pretty much to the bottom, and the last
* rows are being removed. Grid needs to be aware that some
* scrolling is needed, but not to compensate for all the
* removed rows. And it also needs to request for some more rows
* to the top.
*
* 5) Some ranges of rows are removed from view. We need to
* collapse the gaps with existing rows and load the missing
* rows.
*
* 6) The ultimate use case! Grid has 1.5 pages of rows and
* scrolled a bit down. One page of rows is removed. We need to
* make sure that new rows are loaded, but not all old slots are
* occupied, since the page can't be filled with new row data.
* It also needs to be scrolled to the top.
*
* So, it's easier (and safer) to do the simple thing instead of
* taking all the corner cases into account.
*/

pushRows(visibleRows.getStart(), itemIds);
activeRowHandler.setActiveRows(visibleRows.getStart(),
visibleRows.length());
activeRowHandler.activeRange = Range.withLength(0, 0);
activeRowHandler.valueChangeListeners.clear();
rpc.resetDataAndSize(event.getContainer().size());
getState().containerSize = event.getContainer().size();
}
}
};
@@ -613,6 +647,7 @@ public class RpcDataProviderExtension extends AbstractExtension {
*/
public RpcDataProviderExtension(Indexed container) {
this.container = container;
rpc = getRpcProxy(DataProviderRpc.class);

registerRpc(new DataRequestRpc() {
private Collection<String> allTemporarilyPinnedKeys = new ArrayList<String>();
@@ -711,7 +746,7 @@ public class RpcDataProviderExtension extends AbstractExtension {
for (int i = 0; i < itemIds.size(); ++i) {
rows.set(i, getRowData(propertyIds, itemIds.get(i)));
}
getRpcProxy(DataProviderRpc.class).setRowData(firstRow, rows.toJson());
rpc.setRowData(firstRow, rows.toJson());
}

private JsonValue getRowData(Collection<?> propertyIds, Object itemId) {
@@ -766,7 +801,7 @@ public class RpcDataProviderExtension extends AbstractExtension {
*/
private void insertRowData(int index, int count) {
getState().containerSize += count;
getRpcProxy(DataProviderRpc.class).insertRowData(index, count);
rpc.insertRowData(index, count);

activeRowHandler.insertRows(index, count);
}
@@ -783,7 +818,7 @@ public class RpcDataProviderExtension extends AbstractExtension {
*/
private void removeRowData(int firstIndex, int count) {
getState().containerSize -= count;
getRpcProxy(DataProviderRpc.class).removeRowData(firstIndex, count);
rpc.removeRowData(firstIndex, count);

for (int i = 0; i < count; i++) {
Object itemId = keyMapper.itemIdAtIndex(firstIndex + i);
@@ -809,7 +844,7 @@ public class RpcDataProviderExtension extends AbstractExtension {
JsonValue row = getRowData(container.getContainerPropertyIds(), itemId);
JsonArray rowArray = Json.createArray();
rowArray.set(0, row);
getRpcProxy(DataProviderRpc.class).setRowData(index, rowArray.toJson());
rpc.setRowData(index, rowArray.toJson());
}

@Override

+ 12
- 0
shared/src/com/vaadin/shared/data/DataProviderRpc.java 查看文件

@@ -73,4 +73,16 @@ public interface DataProviderRpc extends ClientRpc {
* the number of rows inserted at <code>firstRowIndex</code>
*/
public void insertRowData(int firstRowIndex, int count);

/**
* Resets all data and defines a new size for the data.
* <p>
* This should be used in the cases where the data has changed in some
* unverifiable way. I.e. "something happened". This will lead to a
* re-rendering of the current Grid viewport
*
* @param size
* the size of the new data set
*/
public void resetDataAndSize(int size);
}

+ 23
- 0
uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java 查看文件

@@ -25,6 +25,7 @@ import java.util.List;
import java.util.Locale;
import java.util.Random;

import com.vaadin.data.Container.Filter;
import com.vaadin.data.Item;
import com.vaadin.data.Property;
import com.vaadin.data.util.IndexedContainer;
@@ -209,6 +210,28 @@ public class GridBasicFeatures extends AbstractComponentTest<Grid> {

addHeightActions();

createClickAction("Column 1 starts with \"(23\"", "Filter",
new Command<Grid, Void>() {
@Override
public void execute(Grid grid, Void value, Object data) {
ds.addContainerFilter(new Filter() {

@Override
public boolean passesFilter(Object itemId, Item item)
throws UnsupportedOperationException {
return item.getItemProperty("Column 1")
.getValue().toString()
.startsWith("(23");
}

@Override
public boolean appliesToProperty(Object propertyId) {
return propertyId.equals("Column 1");
}
});
}
}, null);

return grid;
}


+ 26
- 0
uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridStructureTest.java 查看文件

@@ -20,14 +20,17 @@ import static org.hamcrest.core.IsNot.not;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.util.List;

import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebElement;

import com.vaadin.testbench.TestBenchElement;
import com.vaadin.tests.components.grid.GridElement.GridCellElement;
import com.vaadin.testbench.elements.NotificationElement;
import com.vaadin.tests.components.grid.GridElement;
import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeatures;
@@ -229,6 +232,29 @@ public class GridStructureTest extends GridBasicFeaturesTest {
assertTrue(verticalScrollbarIsPresent());
}

@Test
public void testBareItemSetChange() throws Exception {
openTestURL();

selectMenuPath("Component", "Filter", "Column 1 starts with \"(23\"");

boolean foundElements = false;
for (int row = 0; row < 100; row++) {
try {
GridCellElement cell = getGridElement().getCell(row, 1);
foundElements = true;
assertTrue("Unexpected cell contents. "
+ "Did the ItemSetChange work after all?", cell
.getText().startsWith("(23"));
} catch (NoSuchElementException e) {
assertTrue("No rows were found", foundElements);
return;
}
}
fail("unexpected amount of rows post-filter. Did the ItemSetChange work after all?");
}


@Test
public void testRemoveLastColumn() {
setDebug(true);

Loading…
取消
儲存