Browse Source

Grid now supports bare ItemSetChangeEvents (#13334)

Change-Id: Id87b2d7f50720bbfd5011520ea0be32fead48635
tags/7.4.0.beta1
Henrik Paul 9 years ago
parent
commit
8b22659b5b

+ 6
- 0
client/src/com/vaadin/client/data/AbstractRemoteDataSource.java View File

} }
temporarilyPinnedRows = rows; 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 View File

* the number of available rows * the number of available rows
*/ */
public void dataAvailable(int firstRowIndex, int numberOfRows); 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 View File

public void insertRowData(int firstRow, int count) { public void insertRowData(int firstRow, int count) {
dataSource.insertRowData(firstRow, 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 View File

numberOfItems); numberOfItems);
fireEvent(new DataAvailableEvent(currentDataAvailable)); 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(); int previousRowCount = escalator.getBody().getRowCount();

+ 48
- 13
server/src/com/vaadin/data/RpcDataProviderExtension.java View File



private final ActiveRowHandler activeRowHandler = new ActiveRowHandler(); private final ActiveRowHandler activeRowHandler = new ActiveRowHandler();


private DataProviderRpc rpc;

private final ItemSetChangeListener itemListener = new ItemSetChangeListener() { private final ItemSetChangeListener itemListener = new ItemSetChangeListener() {
@Override @Override
public void containerItemSetChange(ItemSetChangeEvent event) { public void containerItemSetChange(ItemSetChangeEvent event) {
} }


else { 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();
} }
} }
}; };
*/ */
public RpcDataProviderExtension(Indexed container) { public RpcDataProviderExtension(Indexed container) {
this.container = container; this.container = container;
rpc = getRpcProxy(DataProviderRpc.class);


registerRpc(new DataRequestRpc() { registerRpc(new DataRequestRpc() {
private Collection<String> allTemporarilyPinnedKeys = new ArrayList<String>(); private Collection<String> allTemporarilyPinnedKeys = new ArrayList<String>();
for (int i = 0; i < itemIds.size(); ++i) { for (int i = 0; i < itemIds.size(); ++i) {
rows.set(i, getRowData(propertyIds, itemIds.get(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) { private JsonValue getRowData(Collection<?> propertyIds, Object itemId) {
*/ */
private void insertRowData(int index, int count) { private void insertRowData(int index, int count) {
getState().containerSize += count; getState().containerSize += count;
getRpcProxy(DataProviderRpc.class).insertRowData(index, count);
rpc.insertRowData(index, count);


activeRowHandler.insertRows(index, count); activeRowHandler.insertRows(index, count);
} }
*/ */
private void removeRowData(int firstIndex, int count) { private void removeRowData(int firstIndex, int count) {
getState().containerSize -= count; getState().containerSize -= count;
getRpcProxy(DataProviderRpc.class).removeRowData(firstIndex, count);
rpc.removeRowData(firstIndex, count);


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


@Override @Override

+ 12
- 0
shared/src/com/vaadin/shared/data/DataProviderRpc.java View File

* the number of rows inserted at <code>firstRowIndex</code> * the number of rows inserted at <code>firstRowIndex</code>
*/ */
public void insertRowData(int firstRowIndex, int count); 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 View File

import java.util.Locale; import java.util.Locale;
import java.util.Random; import java.util.Random;


import com.vaadin.data.Container.Filter;
import com.vaadin.data.Item; import com.vaadin.data.Item;
import com.vaadin.data.Property; import com.vaadin.data.Property;
import com.vaadin.data.util.IndexedContainer; import com.vaadin.data.util.IndexedContainer;


addHeightActions(); 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; return grid;
} }



+ 26
- 0
uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridStructureTest.java View File

import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;


import java.util.List; import java.util.List;


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


import com.vaadin.testbench.TestBenchElement; import com.vaadin.testbench.TestBenchElement;
import com.vaadin.tests.components.grid.GridElement.GridCellElement;
import com.vaadin.testbench.elements.NotificationElement; import com.vaadin.testbench.elements.NotificationElement;
import com.vaadin.tests.components.grid.GridElement; import com.vaadin.tests.components.grid.GridElement;
import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeatures; import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeatures;
assertTrue(verticalScrollbarIsPresent()); 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 @Test
public void testRemoveLastColumn() { public void testRemoveLastColumn() {
setDebug(true); setDebug(true);

Loading…
Cancel
Save