/*
* 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.Comparator;
import java.util.Date;
import java.util.List;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window.Location;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.HasWidgets;
import com.vaadin.client.data.DataChangeHandler;
import com.vaadin.client.data.DataSource;
import com.vaadin.shared.Registration;
import com.vaadin.shared.ui.Connect;
import com.vaadin.tests.widgetset.server.v7.grid.GridClientColumnRenderers;
import com.vaadin.v7.client.renderers.ComplexRenderer;
import com.vaadin.v7.client.renderers.DateRenderer;
import com.vaadin.v7.client.renderers.HtmlRenderer;
import com.vaadin.v7.client.renderers.NumberRenderer;
import com.vaadin.v7.client.renderers.Renderer;
import com.vaadin.v7.client.renderers.TextRenderer;
import com.vaadin.v7.client.renderers.WidgetRenderer;
import com.vaadin.v7.client.ui.AbstractLegacyComponentConnector;
import com.vaadin.v7.client.widget.grid.CellReference;
import com.vaadin.v7.client.widget.grid.RendererCellReference;
import com.vaadin.v7.client.widget.grid.datasources.ListDataSource;
import com.vaadin.v7.client.widget.grid.datasources.ListSorter;
import com.vaadin.v7.client.widget.grid.sort.Sort;
import com.vaadin.v7.client.widget.grid.sort.SortEvent;
import com.vaadin.v7.client.widget.grid.sort.SortHandler;
import com.vaadin.v7.client.widget.grid.sort.SortOrder;
import com.vaadin.v7.client.widgets.Grid;
@Connect(GridClientColumnRenderers.GridController.class)
public class GridClientColumnRendererConnector
extends AbstractLegacyComponentConnector {
public static enum Renderers {
TEXT_RENDERER, WIDGET_RENDERER, HTML_RENDERER, NUMBER_RENDERER, DATE_RENDERER, CPLX_RENDERER;
}
/**
* Datasource for simulating network latency
*/
private class DelayedDataSource implements DataSource<String> {
private DataSource<String> ds;
private int firstRowIndex = -1;
private int numberOfRows;
private DataChangeHandler dataChangeHandler;
private int latency;
private Timer timer;
public DelayedDataSource(DataSource<String> ds, int latency) {
this.ds = ds;
this.latency = latency;
}
@Override
public void ensureAvailability(final int firstRowIndex,
final int numberOfRows) {
timer = new Timer() {
@Override
public void run() {
DelayedDataSource.this.firstRowIndex = firstRowIndex;
DelayedDataSource.this.numberOfRows = numberOfRows;
dataChangeHandler.dataUpdated(firstRowIndex, numberOfRows);
dataChangeHandler.dataAvailable(firstRowIndex,
numberOfRows);
timer = null;
}
};
timer.schedule(latency);
}
@Override
public String getRow(int rowIndex) {
if (rowIndex >= firstRowIndex
&& rowIndex <= firstRowIndex + numberOfRows) {
return ds.getRow(rowIndex);
}
return null;
}
@Override
public int size() {
return ds.size();
}
@Override
public Registration addDataChangeHandler(
DataChangeHandler dataChangeHandler) {
this.dataChangeHandler = dataChangeHandler;
return null;
}
@Override
public RowHandle<String> getHandle(String row) {
// TODO Auto-generated method stub (henrik paul: 17.6.)
return null;
}
@Override
public boolean isWaitingForData() {
return timer != null;
}
}
@Override
protected void init() {
Grid<String> grid = getWidget();
grid.setSelectionMode(Grid.SelectionMode.NONE);
// Generated some column data
List<String> columnData = new ArrayList<>();
for (int i = 0; i < 100; i++) {
columnData.add(String.valueOf(i));
}
// Provide data as data source
if (Location.getParameter("latency") != null) {
grid.setDataSource(new DelayedDataSource(
new ListDataSource<>(columnData),
Integer.parseInt(Location.getParameter("latency"))));
} else {
grid.setDataSource(new ListDataSource<>(columnData));
}
// Add a column to display the data in
Grid.Column<String, String> c = createColumnWithRenderer(
Renderers.TEXT_RENDERER);
grid.addColumn(c);
grid.getDefaultHeaderRow().getCell(c).setText("Column 1");
// Add another column with a custom complex renderer
c = createColumnWithRenderer(Renderers.CPLX_RENDERER);
grid.addColumn(c);
grid.getDefaultHeaderRow().getCell(c).setText("Column 2");
// Add method for testing sort event firing
grid.addSortHandler(new SortHandler<String>() {
@Override
public void sort(SortEvent<String> event) {
Element console = Document.get()
.getElementById("testDebugConsole");
String text = "Client-side sort event received<br>"
+ "Columns: " + event.getOrder().size() + ", order: ";
for (SortOrder order : event.getOrder()) {
String columnHeader = getWidget().getDefaultHeaderRow()
.getCell(order.getColumn()).getText();
text += columnHeader + ": "
+ order.getDirection().toString();
}
console.setInnerHTML(text);
}
});
// Handle RPC calls
registerRpc(GridClientColumnRendererRpc.class,
new GridClientColumnRendererRpc() {
@Override
public void addColumn(Renderers renderer) {
Grid.Column<?, String> column;
if (renderer == Renderers.NUMBER_RENDERER) {
column = createNumberColumnWithRenderer(renderer);
} else if (renderer == Renderers.DATE_RENDERER) {
column = createDateColumnWithRenderer(renderer);
} else {
column = createColumnWithRenderer(renderer);
}
getWidget().addColumn(column);
getWidget().getDefaultHeaderRow().getCell(column)
.setText("Column " + String.valueOf(
getWidget().getColumnCount() + 1));
}
@Override
public void detachAttach() {
// Detach
HasWidgets parent = (HasWidgets) getWidget()
.getParent();
parent.remove(getWidget());
// Re-attach
parent.add(getWidget());
}
@Override
public void triggerClientSorting() {
getWidget().sort(Sort.by(getWidget().getColumn(0)));
}
@Override
@SuppressWarnings("unchecked")
public void triggerClientSortingTest() {
Grid<String> grid = getWidget();
ListSorter<String> sorter = new ListSorter<>(grid);
// Make sorter sort the numbers in natural order
sorter.setComparator(
(Grid.Column<String, String>) grid.getColumn(0),
new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return Integer.parseInt(o1)
- Integer.parseInt(o2);
}
});
// Sort along column 0 in ascending order
grid.sort(grid.getColumn(0));
// Remove the sorter once we're done
sorter.removeFromGrid();
}
@Override
@SuppressWarnings("unchecked")
public void shuffle() {
Grid<String> grid = getWidget();
ListSorter<String> shuffler = new ListSorter<>(grid);
// Make shuffler return random order
shuffler.setComparator(
(Grid.Column<String, String>) grid.getColumn(0),
new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return com.google.gwt.user.client.Random
.nextInt(3) - 1;
}
});
// "Sort" (actually shuffle) along column 0
grid.sort(grid.getColumn(0));
// Remove the shuffler when we're done so that it
// doesn't interfere with further operations
shuffler.removeFromGrid();
}
});
}
/**
* Creates a a renderer for a {@link Renderers}
*/
private Renderer createRenderer(Renderers renderer) {
switch (renderer) {
case TEXT_RENDERER:
return new TextRenderer();
case WIDGET_RENDERER:
return new WidgetRenderer<String, Button>() {
@Override
public Button createWidget() {
final Button button = new Button("");
button.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
button.setText("Clicked");
}
});
return button;
}
@Override
public void render(RendererCellReference cell, String data,
Button button) {
button.setHTML(data);
}
};
case HTML_RENDERER:
return new HtmlRenderer() {
@Override
public void render(RendererCellReference cell,
String htmlString) {
super.render(cell, "<b>" + htmlString + "</b>");
}
};
case NUMBER_RENDERER:
return new NumberRenderer();
case DATE_RENDERER:
return new DateRenderer();
case CPLX_RENDERER:
return new ComplexRenderer<String>() {
@Override
public void init(RendererCellReference cell) {
}
@Override
public void render(RendererCellReference cell, String data) {
cell.getElement().setInnerHTML("<span>" + data + "</span>");
cell.getElement().getStyle().clearBackgroundColor();
}
@Override
public void setContentVisible(RendererCellReference cell,
boolean hasData) {
// Visualize content visible property
cell.getElement().getStyle()
.setBackgroundColor(hasData ? "green" : "red");
super.setContentVisible(cell, hasData);
}
@Override
public boolean onActivate(CellReference<?> cell) {
cell.getElement().setInnerHTML("<span>Activated!</span>");
return true;
}
};
default:
return new TextRenderer();
}
}
private Grid.Column<String, String> createColumnWithRenderer(
Renderers renderer) {
return new Grid.Column<String, String>(createRenderer(renderer)) {
@Override
public String getValue(String row) {
return row;
}
};
}
private Grid.Column<Number, String> createNumberColumnWithRenderer(
Renderers renderer) {
return new Grid.Column<Number, String>(createRenderer(renderer)) {
@Override
public Number getValue(String row) {
return Long.parseLong(row);
}
};
}
private Grid.Column<Date, String> createDateColumnWithRenderer(
Renderers renderer) {
return new Grid.Column<Date, String>(createRenderer(renderer)) {
@Override
public Date getValue(String row) {
return new Date();
}
};
}
@Override
public Grid<String> getWidget() {
return (Grid<String>) super.getWidget();
}
}