aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--client/src/com/vaadin/client/ui/grid/GridConnector.java39
-rw-r--r--server/src/com/vaadin/data/RpcDataProviderExtension.java51
-rw-r--r--server/src/com/vaadin/ui/Grid.java59
-rw-r--r--shared/src/com/vaadin/shared/ui/grid/GridState.java17
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java55
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridCellStyleGeneratorTest.java108
6 files changed, 327 insertions, 2 deletions
diff --git a/client/src/com/vaadin/client/ui/grid/GridConnector.java b/client/src/com/vaadin/client/ui/grid/GridConnector.java
index 2388516a2d..671fd259d6 100644
--- a/client/src/com/vaadin/client/ui/grid/GridConnector.java
+++ b/client/src/com/vaadin/client/ui/grid/GridConnector.java
@@ -41,6 +41,7 @@ import com.vaadin.client.data.RpcDataSourceConnector.RpcDataSource;
import com.vaadin.client.ui.AbstractFieldConnector;
import com.vaadin.client.ui.AbstractHasComponentsConnector;
import com.vaadin.client.ui.SimpleManagedLayout;
+import com.vaadin.client.ui.grid.Grid.CellStyleGenerator;
import com.vaadin.client.ui.grid.GridHeader.HeaderRow;
import com.vaadin.client.ui.grid.renderers.AbstractRendererConnector;
import com.vaadin.client.ui.grid.selection.AbstractRowHandleSelectionModel;
@@ -81,6 +82,35 @@ import com.vaadin.shared.ui.grid.SortDirection;
public class GridConnector extends AbstractHasComponentsConnector implements
SimpleManagedLayout {
+ private static final class CustomCellStyleGenerator implements
+ CellStyleGenerator<JSONObject> {
+ @Override
+ public String getStyle(Grid<JSONObject> grid, JSONObject row,
+ int rowIndex, GridColumn<?, JSONObject> column, int columnIndex) {
+ if (column == null) {
+ JSONValue styleValue = row.get(GridState.JSONKEY_ROWSTYLE);
+ if (styleValue != null) {
+ return styleValue.isString().stringValue();
+ } else {
+ return null;
+ }
+ } else {
+ JSONValue cellstyles = row.get(GridState.JSONKEY_CELLSTYLES);
+ if (cellstyles == null) {
+ return null;
+ }
+
+ CustomGridColumn c = (CustomGridColumn) column;
+ JSONValue styleValue = cellstyles.isObject().get(c.id);
+ if (styleValue != null) {
+ return styleValue.isString().stringValue();
+ } else {
+ return null;
+ }
+ }
+ }
+ }
+
/**
* Custom implementation of the custom grid column using a JSONObject to
* represent the cell value and String as a column type.
@@ -644,6 +674,15 @@ public class GridConnector extends AbstractHasComponentsConnector implements
}
}
+ @OnStateChange("hasCellStyleGenerator")
+ private void onCellStyleGeneratorChange() {
+ if (getState().hasCellStyleGenerator) {
+ getWidget().setCellStyleGenerator(new CustomCellStyleGenerator());
+ } else {
+ getWidget().setCellStyleGenerator(null);
+ }
+ }
+
@OnStateChange("selectedKeys")
private void updateSelectionFromState() {
boolean changed = false;
diff --git a/server/src/com/vaadin/data/RpcDataProviderExtension.java b/server/src/com/vaadin/data/RpcDataProviderExtension.java
index ffef7e5b9e..d607879aa5 100644
--- a/server/src/com/vaadin/data/RpcDataProviderExtension.java
+++ b/server/src/com/vaadin/data/RpcDataProviderExtension.java
@@ -47,6 +47,7 @@ import com.vaadin.shared.data.DataRequestRpc;
import com.vaadin.shared.ui.grid.GridState;
import com.vaadin.shared.ui.grid.Range;
import com.vaadin.ui.Grid;
+import com.vaadin.ui.Grid.CellStyleGenerator;
import com.vaadin.ui.Grid.Column;
import com.vaadin.ui.components.grid.Renderer;
@@ -718,7 +719,6 @@ public class RpcDataProviderExtension extends AbstractExtension {
Grid grid = getGrid();
- int i = 0;
for (Object propertyId : propertyIds) {
Column column = grid.getColumn(propertyId);
@@ -733,9 +733,42 @@ public class RpcDataProviderExtension extends AbstractExtension {
final JsonObject rowObject = Json.createObject();
rowObject.put(GridState.JSONKEY_DATA, rowData);
rowObject.put(GridState.JSONKEY_ROWKEY, keyMapper.getKey(itemId));
+
+ CellStyleGenerator cellStyleGenerator = grid.getCellStyleGenerator();
+ if (cellStyleGenerator != null) {
+ setGeneratedStyles(cellStyleGenerator, rowObject, propertyIds,
+ itemId);
+ }
+
return rowObject;
}
+ private void setGeneratedStyles(CellStyleGenerator generator,
+ JsonObject rowObject, Collection<?> propertyIds, Object itemId) {
+ Grid grid = getGrid();
+
+ JsonObject cellStyles = null;
+ for (Object propertyId : propertyIds) {
+ String style = generator.getStyle(grid, itemId, propertyId);
+ if (style != null) {
+ if (cellStyles == null) {
+ cellStyles = Json.createObject();
+ }
+
+ String columnKey = columnKeys.key(propertyId);
+ cellStyles.put(columnKey, style);
+ }
+ }
+ if (cellStyles != null) {
+ rowObject.put(GridState.JSONKEY_CELLSTYLES, cellStyles);
+ }
+
+ String rowStyle = generator.getStyle(grid, itemId, null);
+ if (rowStyle != null) {
+ rowObject.put(GridState.JSONKEY_ROWSTYLE, rowStyle);
+ }
+ }
+
@Override
protected DataProviderState getState() {
return (DataProviderState) super.getState();
@@ -813,6 +846,22 @@ public class RpcDataProviderExtension extends AbstractExtension {
rpc.setRowData(index, rowArray.toJson());
}
+ /**
+ * Pushes a new version of all the rows in the active cache range.
+ */
+ public void refreshCache() {
+ if (!clientInitialized) {
+ return;
+ }
+
+ int firstRow = activeRowHandler.activeRange.getStart();
+ int numberOfRows = activeRowHandler.activeRange.length();
+
+ List<?> itemIds = RpcDataProviderExtension.this.container.getItemIds(
+ firstRow, numberOfRows);
+ pushRows(firstRow, itemIds);
+ }
+
@Override
public void setParent(ClientConnector parent) {
super.setParent(parent);
diff --git a/server/src/com/vaadin/ui/Grid.java b/server/src/com/vaadin/ui/Grid.java
index 9732aa4612..992c666709 100644
--- a/server/src/com/vaadin/ui/Grid.java
+++ b/server/src/com/vaadin/ui/Grid.java
@@ -201,6 +201,37 @@ public class Grid extends AbstractComponent implements SelectionChangeNotifier,
}
/**
+ * Callback interface for generating custom style names for data rows and
+ * cells.
+ *
+ * @see Grid#setCellStyleGenerator(CellStyleGenerator)
+ */
+ public interface CellStyleGenerator extends Serializable {
+
+ /**
+ * Called by Grid to generate a style name for a row or cell element.
+ * Row styles are generated when the column parameter is
+ * <code>null</code>, otherwise a cell style is generated.
+ * <p>
+ * The returned style name is prefixed so that the actual style for
+ * cells will be <tt>v-grid-cell-content-[style name]</tt>, and the row
+ * style will be <tt>v-grid-row-[style name]</tt>.
+ *
+ * @param grid
+ * the source grid
+ * @param itemId
+ * the itemId of the target row
+ * @param propertyId
+ * the propertyId of the target cell, <code>null</code> when
+ * getting row style
+ * @return the style name to add to this cell or row element, or
+ * <code>null</code> to not set any style
+ */
+ public abstract String getStyle(Grid grid, Object itemId,
+ Object propertyId);
+ }
+
+ /**
* Abstract base class for Grid header and footer sections.
*
* @param <ROWTYPE>
@@ -1941,6 +1972,8 @@ public class Grid extends AbstractComponent implements SelectionChangeNotifier,
private EditorRow editorRow;
+ private CellStyleGenerator cellStyleGenerator;
+
/**
* <code>true</code> if Grid is using the internal IndexedContainer created
* in Grid() constructor, or <code>false</code> if the user has set their
@@ -3551,4 +3584,30 @@ public class Grid extends AbstractComponent implements SelectionChangeNotifier,
EditorRowClientRpc getEditorRowRpc() {
return getRpcProxy(EditorRowClientRpc.class);
}
+
+ /**
+ * Sets the cell style generator that is used for generating styles for rows
+ * and cells.
+ *
+ * @param cellStyleGenerator
+ * the cell style generator to set, or <code>null</code> to
+ * remove a previously set generator
+ */
+ public void setCellStyleGenerator(CellStyleGenerator cellStyleGenerator) {
+ this.cellStyleGenerator = cellStyleGenerator;
+ getState().hasCellStyleGenerator = (cellStyleGenerator != null);
+
+ datasourceExtension.refreshCache();
+ }
+
+ /**
+ * Gets the cell style generator that is used for generating styles for rows
+ * and cells.
+ *
+ * @return the cell style generator, or <code>null</code> if no generator is
+ * set
+ */
+ public CellStyleGenerator getCellStyleGenerator() {
+ return cellStyleGenerator;
+ }
}
diff --git a/shared/src/com/vaadin/shared/ui/grid/GridState.java b/shared/src/com/vaadin/shared/ui/grid/GridState.java
index 934ba25884..621b34a2b4 100644
--- a/shared/src/com/vaadin/shared/ui/grid/GridState.java
+++ b/shared/src/com/vaadin/shared/ui/grid/GridState.java
@@ -88,6 +88,20 @@ public class GridState extends AbstractComponentState {
public static final String JSONKEY_ROWKEY = "k";
/**
+ * The key in which a row's generated style can be found
+ *
+ * @see com.vaadin.shared.data.DataProviderRpc#setRowData(int, String)
+ */
+ public static final String JSONKEY_ROWSTYLE = "rs";
+
+ /**
+ * The key in which a generated styles for a row's cells can be found
+ *
+ * @see com.vaadin.shared.data.DataProviderRpc#setRowData(int, String)
+ */
+ public static final String JSONKEY_CELLSTYLES = "cs";
+
+ /**
* Columns in grid.
*/
public List<GridColumnState> columns = new ArrayList<GridColumnState>();
@@ -129,4 +143,7 @@ public class GridState extends AbstractComponentState {
/** The enabled state of the editor row */
public boolean editorRowEnabled = false;
+
+ /** Whether row data might contain generated styles */
+ public boolean hasCellStyleGenerator;
}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java
index c97d92249a..ccbb85da08 100644
--- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java
@@ -38,8 +38,9 @@ import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.Grid;
-import com.vaadin.ui.Grid.FooterCell;
+import com.vaadin.ui.Grid.CellStyleGenerator;
import com.vaadin.ui.Grid.Column;
+import com.vaadin.ui.Grid.FooterCell;
import com.vaadin.ui.Grid.HeaderCell;
import com.vaadin.ui.Grid.HeaderRow;
import com.vaadin.ui.Grid.SelectionMode;
@@ -285,6 +286,58 @@ public class GridBasicFeatures extends AbstractComponentTest<Grid> {
}
}
});
+
+ LinkedHashMap<String, CellStyleGenerator> styleGenerators = new LinkedHashMap<String, CellStyleGenerator>();
+ styleGenerators.put("None", null);
+ styleGenerators.put("Row only", new CellStyleGenerator() {
+ @Override
+ public String getStyle(Grid grid, Object itemId, Object propertyId) {
+ if (propertyId == null) {
+ return "row" + itemId;
+ } else {
+ return null;
+ }
+ }
+ });
+ styleGenerators.put("Cell only", new CellStyleGenerator() {
+ @Override
+ public String getStyle(Grid grid, Object itemId, Object propertyId) {
+ if (propertyId == null) {
+ return null;
+ } else {
+ return propertyId.toString().replace(' ', '-');
+ }
+ }
+ });
+ styleGenerators.put("Combined", new CellStyleGenerator() {
+ @Override
+ public String getStyle(Grid grid, Object itemId, Object propertyId) {
+ int rowIndex = ((Integer) itemId).intValue();
+ if (propertyId == null) {
+ if (rowIndex % 4 == 0) {
+ return null;
+ } else {
+ return "row" + itemId;
+ }
+ } else {
+ if (rowIndex % 4 == 1) {
+ return null;
+ } else if (rowIndex % 4 == 3
+ && "Column 1".equals(propertyId)) {
+ return null;
+ }
+ return propertyId.toString().replace(' ', '_');
+ }
+ }
+ });
+ createSelectAction("Style generator", "State", styleGenerators, "None",
+ new Command<Grid, CellStyleGenerator>() {
+ @Override
+ public void execute(Grid grid,
+ CellStyleGenerator generator, Object data) {
+ grid.setCellStyleGenerator(generator);
+ }
+ });
}
protected void createHeaderActions() {
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridCellStyleGeneratorTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridCellStyleGeneratorTest.java
new file mode 100644
index 0000000000..24a575789e
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridCellStyleGeneratorTest.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2000-2014 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.components.grid.basicfeatures.server;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.tests.components.grid.GridElement.GridCellElement;
+import com.vaadin.tests.components.grid.GridElement.GridRowElement;
+import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeaturesTest;
+
+public class GridCellStyleGeneratorTest extends GridBasicFeaturesTest {
+ @Test
+ public void testStyleNameGeneratorScrolling() throws Exception {
+ openTestURL();
+
+ selectStyleNameGenerator("Combined");
+
+ GridRowElement row2 = getGridElement().getRow(2);
+ GridCellElement cell3_2 = getGridElement().getCell(3, 2);
+
+ Assert.assertTrue(row2.getAttribute("class")
+ .contains("v-grid-row-row2"));
+ Assert.assertTrue(cell3_2.getAttribute("class").contains(
+ "v-grid-cell-content-Column_2"));
+
+ // Scroll down and verify that the old elements don't have the
+ // stylename any more
+
+ // Carefully chosen offset to hit an index % 4 without cell style
+ getGridElement().getRow(352);
+
+ Assert.assertFalse(row2.getAttribute("class").contains(
+ "v-grid-row-row2"));
+ Assert.assertFalse(cell3_2.getAttribute("class").contains(
+ "v-grid-cell-content-Column_2"));
+ }
+
+ @Test
+ public void testDisableStyleNameGenerator() throws Exception {
+ openTestURL();
+
+ selectStyleNameGenerator("Combined");
+
+ // Just verify that change was effective
+ GridRowElement row2 = getGridElement().getRow(2);
+ GridCellElement cell3_2 = getGridElement().getCell(3, 2);
+
+ Assert.assertTrue(row2.getAttribute("class")
+ .contains("v-grid-row-row2"));
+ Assert.assertTrue(cell3_2.getAttribute("class").contains(
+ "v-grid-cell-content-Column_2"));
+
+ // Disable the generator and check again
+ selectStyleNameGenerator("None");
+
+ Assert.assertFalse(row2.getAttribute("class").contains(
+ "v-grid-row-row2"));
+ Assert.assertFalse(cell3_2.getAttribute("class").contains(
+ "v-grid-cell-content-Column_2"));
+ }
+
+ @Test
+ public void testChangeStyleNameGenerator() throws Exception {
+ openTestURL();
+
+ selectStyleNameGenerator("Combined");
+
+ // Just verify that change was effective
+ GridRowElement row2 = getGridElement().getRow(2);
+ GridCellElement cell3_2 = getGridElement().getCell(3, 2);
+
+ Assert.assertTrue(row2.getAttribute("class")
+ .contains("v-grid-row-row2"));
+ Assert.assertTrue(cell3_2.getAttribute("class").contains(
+ "v-grid-cell-content-Column_2"));
+
+ // Change the generator and check again
+ selectStyleNameGenerator("Cell only");
+
+ // Old styles removed?
+ Assert.assertFalse(row2.getAttribute("class").contains(
+ "v-grid-row-row2"));
+ Assert.assertFalse(cell3_2.getAttribute("class").contains(
+ "v-grid-cell-content-Column_2"));
+
+ // New style present?
+ Assert.assertTrue(cell3_2.getAttribute("class").contains(
+ "v-grid-cell-content-Column-2"));
+ }
+
+ private void selectStyleNameGenerator(String name) {
+ selectMenuPath("Component", "State", "Style generator", name);
+ }
+}