/*
* Copyright 2000-2016 Vaadin Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.vaadin.tests.widgetset.client.v7.grid;
import java.util.ArrayList;
import java.util.List;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.vaadin.client.data.AbstractRemoteDataSource;
import com.vaadin.v7.client.renderers.TextRenderer;
import com.vaadin.v7.client.widgets.Grid;
import com.vaadin.v7.client.widgets.Grid.SelectionMode;
public class GridClientDataSourcesWidget
extends PureGWTTestApplication<Grid<String[]>> {
private interface RestCallback {
void onResponse(RestishDataSource.Backend.Result result);
}
/**
* This is an emulated datasource that has a back-end that changes size
* constantly. The back-end is unable to actively push data to Grid.
* Instead, with each row request, in addition to its row payload it tells
* how many rows it contains in total.
*
* A plausible response from this REST-like api would be:
*
* <pre>
* <code>
* GET /foos/4..8
*
* {
* "resultsize": 4,
* "data": [
* [4, "foo IV"],
* [5, "foo V"],
* [6, "foo VI"]
* [7, "foo VII"]
* ],
* "totalrows": 100
* }
* </code>
* </pre>
*
* In this case, the size of Grid needs to be updated to be able to show 100
* rows in total (no more, no less).
*
* This class
* <ol>
* <li>gets initialized
* <li>asks for its size
* <li>updates Grid once the reply is received
* <li>as the Grid fetches more data, the total row count is dynamically
* updated.
* </ol>
*/
private class RestishDataSource extends AbstractRemoteDataSource<String[]> {
/**
* Pretend like this class doesn't exist. It just simulates a backend
* somewhere.
* <p>
* It's scoped inside the RDS class only because it's tied to that.
*/
private class Backend {
public class Result {
public int size;
public List<String[]> rows;
}
private int size = 200;
private int modCount = 0;
public void query(int firstRowIndex, int numberOfRows,
final RestCallback callback) {
final Result result = new Result();
result.size = size;
result.rows = fetchRows(firstRowIndex, numberOfRows);
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
@Override
public void execute() {
callback.onResponse(result);
}
});
}
private List<String[]> fetchRows(int firstRowIndex,
int numberOfRows) {
List<String[]> rows = new ArrayList<>();
for (int i = 0; i < numberOfRows; i++) {
String id = String.valueOf(firstRowIndex + i);
rows.add(new String[] { id,
"cell " + id + " #" + modCount });
}
return rows;
}
public void pushRowChanges(int rows) {
size += rows;
pushRowChanges();
}
public void pushRowChanges() {
modCount++;
// push "something happened" to datasource "over the wire":
resetDataAndSize(size);
}
public void addRows(int rowcount) {
modCount++;
size += rowcount;
}
}
final Backend backend;
public RestishDataSource() {
backend = new Backend();
}
@Override
protected void requestRows(int firstRowIndex, int numberOfRows,
final RequestRowsCallback<String[]> callback) {
backend.query(firstRowIndex, numberOfRows, new RestCallback() {
@Override
public void onResponse(Backend.Result result) {
callback.onResponse(result.rows, result.size);
}
});
}
@Override
public Object getRowKey(String[] row) {
return row[0];
}
}
private final Grid<String[]> grid;
private RestishDataSource restishDataSource;
private final ScheduledCommand setRestishCommand = new ScheduledCommand() {
@Override
public void execute() {
for (Grid.Column<?, String[]> column : grid.getColumns()) {
grid.removeColumn(column);
}
restishDataSource = new RestishDataSource();
grid.setDataSource(restishDataSource);
grid.addColumn(new Grid.Column<String, String[]>("column",
new TextRenderer()) {
@Override
public String getValue(String[] row) {
return row[1];
}
});
}
};
public GridClientDataSourcesWidget() {
super(new Grid<String[]>());
grid = getTestedWidget();
grid.getElement().getStyle().setZIndex(0);
grid.setHeight("400px");
grid.setSelectionMode(SelectionMode.NONE);
addNorth(grid, 400);
addMenuCommand("Use", setRestishCommand, "DataSources", "RESTish");
addMenuCommand("Next request +10", new ScheduledCommand() {
@Override
public void execute() {
restishDataSource.backend.addRows(10);
}
}, "DataSources", "RESTish");
addMenuCommand("Next request -10", new ScheduledCommand() {
@Override
public void execute() {
restishDataSource.backend.addRows(-10);
}
}, "DataSources", "RESTish");
addMenuCommand("Push data change", new ScheduledCommand() {
@Override
public void execute() {
restishDataSource.backend.pushRowChanges();
}
}, "DataSources", "RESTish");
addMenuCommand("Push data change +10", new ScheduledCommand() {
@Override
public void execute() {
restishDataSource.backend.pushRowChanges(10);
}
}, "DataSources", "RESTish");
addMenuCommand("Push data change -10", new ScheduledCommand() {
@Override
public void execute() {
restishDataSource.backend.pushRowChanges(-10);
}
}, "DataSources", "RESTish");
}
}