summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTeemu Suo-Anttila <teemusa@vaadin.com>2016-09-06 15:07:37 +0300
committerArtur Signell <artur@vaadin.com>2016-09-08 11:33:14 +0000
commit74df0fadeb7d6c2a6e15b4716602d6ab7ffb54b1 (patch)
tree8d913860bc0e2fb9b14dafcf8cff149e641aea1a
parent8a4d90789ffd6a28ce29870bd176ace62f33288f (diff)
downloadvaadin-framework-74df0fadeb7d6c2a6e15b4716602d6ab7ffb54b1.tar.gz
vaadin-framework-74df0fadeb7d6c2a6e15b4716602d6ab7ffb54b1.zip
Add StyleGenerators for Grid and Columns
Change-Id: I5eedce6ac24381d657357ff07ca1ccedd804158d
-rw-r--r--client/src/main/java/com/vaadin/client/connectors/grid/GridConnector.java23
-rw-r--r--server/src/main/java/com/vaadin/server/data/DataCommunicator.java2
-rw-r--r--server/src/main/java/com/vaadin/ui/Grid.java110
-rw-r--r--uitest/src/main/java/com/vaadin/tests/components/grid/basics/GridBasics.java58
-rw-r--r--uitest/src/test/java/com/vaadin/tests/components/grid/basics/GridBasicStyleGeneratorTest.java155
-rw-r--r--uitest/src/test/java/com/vaadin/tests/components/grid/basics/GridContentTest.java4
6 files changed, 337 insertions, 15 deletions
diff --git a/client/src/main/java/com/vaadin/client/connectors/grid/GridConnector.java b/client/src/main/java/com/vaadin/client/connectors/grid/GridConnector.java
index ab0f6037f1..880de07d55 100644
--- a/client/src/main/java/com/vaadin/client/connectors/grid/GridConnector.java
+++ b/client/src/main/java/com/vaadin/client/connectors/grid/GridConnector.java
@@ -76,6 +76,29 @@ public class GridConnector
// Default selection style is space key.
spaceSelectHandler = new SpaceSelectHandler<JsonObject>(getWidget());
getWidget().addSortHandler(this::handleSortEvent);
+ getWidget().setRowStyleGenerator(rowRef -> {
+ JsonObject json = rowRef.getRow();
+ return json.hasKey(GridState.JSONKEY_ROWSTYLE)
+ ? json.getString(GridState.JSONKEY_ROWSTYLE) : null;
+ });
+ getWidget().setCellStyleGenerator(cellRef -> {
+ JsonObject row = cellRef.getRow();
+ if (!row.hasKey(GridState.JSONKEY_CELLSTYLES)) {
+ return null;
+ }
+
+ Column<?, JsonObject> column = cellRef.getColumn();
+ if (columnToIdMap.containsKey(column)) {
+ String id = columnToIdMap.get(column);
+ JsonObject cellStyles = row
+ .getObject(GridState.JSONKEY_CELLSTYLES);
+ if (cellStyles.hasKey(id)) {
+ return cellStyles.getString(id);
+ }
+ }
+
+ return null;
+ });
layout();
}
diff --git a/server/src/main/java/com/vaadin/server/data/DataCommunicator.java b/server/src/main/java/com/vaadin/server/data/DataCommunicator.java
index e8c96fddab..b0ade744de 100644
--- a/server/src/main/java/com/vaadin/server/data/DataCommunicator.java
+++ b/server/src/main/java/com/vaadin/server/data/DataCommunicator.java
@@ -357,7 +357,7 @@ public class DataCommunicator<T> extends AbstractExtension {
/**
* Informs the DataProvider that the collection has changed.
*/
- protected void reset() {
+ public void reset() {
if (reset) {
return;
}
diff --git a/server/src/main/java/com/vaadin/ui/Grid.java b/server/src/main/java/com/vaadin/ui/Grid.java
index 94a3dd0ce9..96d7376816 100644
--- a/server/src/main/java/com/vaadin/ui/Grid.java
+++ b/server/src/main/java/com/vaadin/ui/Grid.java
@@ -32,9 +32,7 @@ import java.util.function.Function;
import java.util.stream.Stream;
import com.vaadin.data.selection.SingleSelection;
-import com.vaadin.server.AbstractExtension;
import com.vaadin.server.KeyMapper;
-import com.vaadin.server.data.DataGenerator;
import com.vaadin.server.data.SortOrder;
import com.vaadin.shared.MouseEventDetails;
import com.vaadin.shared.data.DataCommunicatorConstants;
@@ -65,6 +63,17 @@ public class Grid<T> extends AbstractListing<T, SelectionModel<T>>
implements HasComponents {
/**
+ * A callback interface for generating style names for an item.
+ *
+ * @param <T>
+ * the grid bean type
+ */
+ @FunctionalInterface
+ public interface StyleGenerator<T>
+ extends Function<T, String>, Serializable {
+ }
+
+ /**
* A callback interface for generating details for a particular row in Grid.
*
* @param <T>
@@ -304,13 +313,13 @@ public class Grid<T> extends AbstractListing<T, SelectionModel<T>>
* @param <V>
* the column value type
*/
- public static class Column<T, V> extends AbstractExtension
- implements DataGenerator<T> {
+ public static class Column<T, V> extends AbstractGridExtension<T> {
private final Function<T, ? extends V> valueProvider;
private Function<SortDirection, Stream<SortOrder<String>>> sortOrderProvider;
private Comparator<T> comparator;
+ private StyleGenerator<T> styleGenerator;
/**
* Constructs a new Column configuration with given header caption,
@@ -401,22 +410,41 @@ public class Grid<T> extends AbstractListing<T, SelectionModel<T>>
@SuppressWarnings("unchecked")
Renderer<V> renderer = (Renderer<V>) state.renderer;
- if (!jsonObject.hasKey(DataCommunicatorConstants.DATA)) {
- jsonObject.put(DataCommunicatorConstants.DATA,
- Json.createObject());
- }
- JsonObject obj = jsonObject
- .getObject(DataCommunicatorConstants.DATA);
+ JsonObject obj = getDataObject(jsonObject,
+ DataCommunicatorConstants.DATA);
V providerValue = valueProvider.apply(data);
JsonValue rendererValue = renderer.encode(providerValue);
obj.put(communicationId, rendererValue);
+
+ if (styleGenerator != null) {
+ String style = styleGenerator.apply(data);
+ if (style != null && !style.isEmpty()) {
+ JsonObject styleObj = getDataObject(jsonObject,
+ GridState.JSONKEY_CELLSTYLES);
+ styleObj.put(getState(false).id, style);
+ }
+ }
}
- @Override
- public void destroyData(T data) {
+ /**
+ * Gets a data object with the given key from the given JsonObject. If
+ * there is no object with the key, this method creates a new
+ * JsonObject.
+ *
+ * @param jsonObject
+ * the json object
+ * @param key
+ * the key where the desired data object is stored
+ * @return data object for the given key
+ */
+ private JsonObject getDataObject(JsonObject jsonObject, String key) {
+ if (!jsonObject.hasKey(key)) {
+ jsonObject.put(key, Json.createObject());
+ }
+ return jsonObject.getObject(key);
}
@Override
@@ -572,6 +600,33 @@ public class Grid<T> extends AbstractListing<T, SelectionModel<T>>
public Stream<SortOrder<String>> getSortOrder(SortDirection direction) {
return sortOrderProvider.apply(direction);
}
+
+ /**
+ * Sets the style generator that is used for generating styles for cells
+ * in this column.
+ *
+ * @param cellStyleGenerator
+ * the cell style generator to set, or <code>null</code> to
+ * remove a previously set generator
+ * @return this column
+ */
+ public Column<T, V> setStyleGenerator(
+ StyleGenerator<T> cellStyleGenerator) {
+ this.styleGenerator = cellStyleGenerator;
+ getParent().getDataCommunicator().reset();
+ return this;
+ }
+
+ /**
+ * Gets the style generator that is used for generating styles for
+ * cells.
+ *
+ * @return the cell style generator, or <code>null</code> if no
+ * generator is set
+ */
+ public StyleGenerator<T> getStyleGenerator() {
+ return styleGenerator;
+ }
}
private KeyMapper<Column<T, ?>> columnKeys = new KeyMapper<>();
@@ -579,6 +634,7 @@ public class Grid<T> extends AbstractListing<T, SelectionModel<T>>
private List<SortOrder<Column<T, ?>>> sortOrder = new ArrayList<>();
private DetailsManager<T> detailsManager;
private Set<Component> extensionComponents = new HashSet<>();
+ private StyleGenerator<T> styleGenerator;
/**
* Constructor for the {@link Grid} component.
@@ -589,6 +645,14 @@ public class Grid<T> extends AbstractListing<T, SelectionModel<T>>
detailsManager = new DetailsManager<>();
addExtension(detailsManager);
addDataGenerator(detailsManager);
+ addDataGenerator((item, json) -> {
+ if (styleGenerator != null) {
+ String styleName = styleGenerator.apply(item);
+ if (styleName != null && !styleName.isEmpty()) {
+ json.put(GridState.JSONKEY_ROWSTYLE, styleName);
+ }
+ }
+ });
}
/**
@@ -836,6 +900,28 @@ public class Grid<T> extends AbstractListing<T, SelectionModel<T>>
return getState(false).heightMode;
}
+ /**
+ * Sets the style generator that is used for generating styles for rows.
+ *
+ * @param styleGenerator
+ * the row style generator to set, or <code>null</code> to remove
+ * a previously set generator
+ */
+ public void setStyleGenerator(StyleGenerator<T> styleGenerator) {
+ this.styleGenerator = styleGenerator;
+ getDataCommunicator().reset();
+ }
+
+ /**
+ * Gets the style generator that is used for generating styles for rows.
+ *
+ * @return the row style generator, or <code>null</code> if no generator is
+ * set
+ */
+ public StyleGenerator<T> getStyleGenerator() {
+ return styleGenerator;
+ }
+
@Override
protected GridState getState() {
return getState(true);
diff --git a/uitest/src/main/java/com/vaadin/tests/components/grid/basics/GridBasics.java b/uitest/src/main/java/com/vaadin/tests/components/grid/basics/GridBasics.java
index a47d8b3e9e..5c9f03336e 100644
--- a/uitest/src/main/java/com/vaadin/tests/components/grid/basics/GridBasics.java
+++ b/uitest/src/main/java/com/vaadin/tests/components/grid/basics/GridBasics.java
@@ -18,6 +18,7 @@ import com.vaadin.ui.Component;
import com.vaadin.ui.CssLayout;
import com.vaadin.ui.Grid;
import com.vaadin.ui.Grid.DetailsGenerator;
+import com.vaadin.ui.Grid.StyleGenerator;
import com.vaadin.ui.Label;
import com.vaadin.ui.MenuBar;
import com.vaadin.ui.MenuBar.MenuItem;
@@ -32,6 +33,17 @@ import com.vaadin.ui.renderers.ProgressBarRenderer;
@Widgetset("com.vaadin.DefaultWidgetSet")
public class GridBasics extends AbstractTestUIWithLog {
+ public static final String ROW_STYLE_GENERATOR_ROW_NUMBERS_FOR_3_OF_4 = "Row numbers for 3/4";
+ public static final String ROW_STYLE_GENERATOR_NONE = "None";
+ public static final String ROW_STYLE_GENERATOR_ROW_NUMBERS = "Row numbers";
+ public static final String ROW_STYLE_GENERATOR_EMPTY = "Empty string";
+ public static final String ROW_STYLE_GENERATOR_NULL = "Null";
+ public static final String CELL_STYLE_GENERATOR_NONE = "None";
+ public static final String CELL_STYLE_GENERATOR_PROPERTY_TO_STRING = "Property to string";
+ public static final String CELL_STYLE_GENERATOR_SPECIAL = "Special for 1/4 Column 1";
+ public static final String CELL_STYLE_GENERATOR_EMPTY = "Empty string";
+ public static final String CELL_STYLE_GENERATOR_NULL = "Null";
+
private static class DetailedDetailsGenerator
implements DetailsGenerator<DataObject> {
@@ -120,6 +132,8 @@ public class GridBasics extends AbstractTestUIWithLog {
dataObj -> "(" + dataObj.getRowNumber() + ", 0)");
grid.addColumn("Column 1",
dataObj -> "(" + dataObj.getRowNumber() + ", 1)");
+ grid.addColumn("Column 2",
+ dataObj -> "(" + dataObj.getRowNumber() + ", 2)");
grid.addColumn("Row Number", DataObject::getRowNumber,
new NumberRenderer());
@@ -172,6 +186,50 @@ public class GridBasics extends AbstractTestUIWithLog {
addGridMethodMenu(frozenColMenu, "" + i, i,
grid::setFrozenColumnCount);
}
+ createRowStyleMenu(stateMenu.addItem("Row style generator", null));
+ createCellStyleMenu(stateMenu.addItem("Cell style generator", null));
+ }
+
+ private void createRowStyleMenu(MenuItem rowStyleMenu) {
+ addGridMethodMenu(rowStyleMenu, ROW_STYLE_GENERATOR_NONE, null,
+ grid::setStyleGenerator);
+ addGridMethodMenu(rowStyleMenu, ROW_STYLE_GENERATOR_ROW_NUMBERS,
+ t -> "row" + t.getRowNumber(), grid::setStyleGenerator);
+ addGridMethodMenu(rowStyleMenu,
+ ROW_STYLE_GENERATOR_ROW_NUMBERS_FOR_3_OF_4,
+ t -> t.getRowNumber() % 4 != 0 ? "row" + t.getRowNumber()
+ : null,
+ grid::setStyleGenerator);
+ addGridMethodMenu(rowStyleMenu, ROW_STYLE_GENERATOR_EMPTY, t -> "",
+ grid::setStyleGenerator);
+ addGridMethodMenu(rowStyleMenu, ROW_STYLE_GENERATOR_NULL, t -> null,
+ grid::setStyleGenerator);
+ }
+
+ private void createCellStyleMenu(MenuItem cellStyleMenu) {
+ addGridMethodMenu(cellStyleMenu, CELL_STYLE_GENERATOR_NONE,
+ (StyleGenerator<DataObject>) null,
+ sg -> grid.getColumns().forEach(c -> c.setStyleGenerator(sg)));
+ addGridMethodMenu(cellStyleMenu, CELL_STYLE_GENERATOR_EMPTY,
+ (StyleGenerator<DataObject>) t -> "",
+ sg -> grid.getColumns().forEach(c -> c.setStyleGenerator(sg)));
+ addGridMethodMenu(cellStyleMenu,
+ CELL_STYLE_GENERATOR_PROPERTY_TO_STRING, null,
+ sg -> grid.getColumns().forEach(c -> c.setStyleGenerator(
+ t -> c.getCaption().replaceAll(" ", "-"))));
+ addGridMethodMenu(cellStyleMenu, CELL_STYLE_GENERATOR_SPECIAL, null,
+ sg -> grid.getColumns().forEach(c -> c.setStyleGenerator(t -> {
+ if (t.getRowNumber() % 4 == 1) {
+ return null;
+ } else if (t.getRowNumber() % 4 == 3
+ && c.getCaption().equals("Column 1")) {
+ return null;
+ }
+ return c.getCaption().replaceAll(" ", "_");
+ })));
+ addGridMethodMenu(cellStyleMenu, CELL_STYLE_GENERATOR_NULL,
+ (StyleGenerator<DataObject>) t -> null,
+ sg -> grid.getColumns().forEach(c -> c.setStyleGenerator(sg)));
}
private <T> void addGridMethodMenu(MenuItem parent, String name, T value,
diff --git a/uitest/src/test/java/com/vaadin/tests/components/grid/basics/GridBasicStyleGeneratorTest.java b/uitest/src/test/java/com/vaadin/tests/components/grid/basics/GridBasicStyleGeneratorTest.java
new file mode 100644
index 0000000000..b9b93fa884
--- /dev/null
+++ b/uitest/src/test/java/com/vaadin/tests/components/grid/basics/GridBasicStyleGeneratorTest.java
@@ -0,0 +1,155 @@
+/*
+ * 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.components.grid.basics;
+
+import static org.junit.Assert.assertFalse;
+
+import org.junit.Assert;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import com.vaadin.testbench.elements.GridElement.GridCellElement;
+import com.vaadin.testbench.elements.GridElement.GridRowElement;
+import com.vaadin.testbench.elements.NotificationElement;
+
+public class GridBasicStyleGeneratorTest extends GridBasicsTest {
+ @Test
+ public void testStyleNameGeneratorScrolling() throws Exception {
+ openTestURL();
+
+ selectRowStyleNameGenerator(
+ GridBasics.ROW_STYLE_GENERATOR_ROW_NUMBERS_FOR_3_OF_4);
+ selectCellStyleNameGenerator(GridBasics.CELL_STYLE_GENERATOR_SPECIAL);
+
+ GridRowElement row = getGridElement().getRow(2);
+ GridCellElement cell = getGridElement().getCell(3, 2);
+
+ Assert.assertTrue(hasCssClass(row, "row2"));
+ Assert.assertTrue(hasCssClass(cell, "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
+ row = getGridElement().getRow(352);
+ cell = getGridElement().getCell(353, 2);
+
+ Assert.assertFalse(hasCssClass(row, "row352"));
+ Assert.assertFalse(hasCssClass(cell, "Column_2"));
+ }
+
+ @Test
+ public void testDisableStyleNameGenerator() throws Exception {
+ openTestURL();
+
+ selectRowStyleNameGenerator(
+ GridBasics.ROW_STYLE_GENERATOR_ROW_NUMBERS_FOR_3_OF_4);
+ selectCellStyleNameGenerator(GridBasics.CELL_STYLE_GENERATOR_SPECIAL);
+
+ // Just verify that change was effective
+ GridRowElement row = getGridElement().getRow(2);
+ GridCellElement cell = getGridElement().getCell(3, 2);
+
+ Assert.assertTrue(hasCssClass(row, "row2"));
+ Assert.assertTrue(hasCssClass(cell, "Column_2"));
+
+ // Disable the generator and check again
+ selectRowStyleNameGenerator(GridBasics.ROW_STYLE_GENERATOR_NONE);
+ selectCellStyleNameGenerator(GridBasics.CELL_STYLE_GENERATOR_NONE);
+
+ row = getGridElement().getRow(2);
+ cell = getGridElement().getCell(3, 2);
+
+ Assert.assertFalse(hasCssClass(row, "row2"));
+ Assert.assertFalse(hasCssClass(cell, "Column_2"));
+ }
+
+ @Test
+ public void testChangeStyleNameGenerator() throws Exception {
+ openTestURL();
+
+ selectRowStyleNameGenerator(
+ GridBasics.ROW_STYLE_GENERATOR_ROW_NUMBERS_FOR_3_OF_4);
+ selectCellStyleNameGenerator(GridBasics.CELL_STYLE_GENERATOR_SPECIAL);
+
+ // Just verify that change was effective
+ GridRowElement row = getGridElement().getRow(2);
+ GridCellElement cell = getGridElement().getCell(3, 2);
+
+ Assert.assertTrue(hasCssClass(row, "row2"));
+ Assert.assertTrue(hasCssClass(cell, "Column_2"));
+
+ // Change the generator and check again
+ selectRowStyleNameGenerator(GridBasics.ROW_STYLE_GENERATOR_NONE);
+ selectCellStyleNameGenerator(
+ GridBasics.CELL_STYLE_GENERATOR_PROPERTY_TO_STRING);
+
+ row = getGridElement().getRow(2);
+ cell = getGridElement().getCell(3, 2);
+
+ // Old styles removed?
+ Assert.assertFalse(hasCssClass(row, "row2"));
+ Assert.assertFalse(hasCssClass(cell, "Column_2"));
+
+ // New style present?
+ Assert.assertTrue(hasCssClass(cell, "Column-2"));
+ }
+
+ @Test
+ @Ignore
+ public void testCellStyleGeneratorWithSelectionColumn() {
+ setDebug(true);
+ openTestURL();
+ selectMenuPath("Component", "State", "Selection mode", "multi");
+
+ selectCellStyleNameGenerator(GridBasics.CELL_STYLE_GENERATOR_SPECIAL);
+
+ assertFalse("Error notification was present",
+ isElementPresent(NotificationElement.class));
+ }
+
+ private void selectRowStyleNameGenerator(String name) {
+ selectMenuPath("Component", "State", "Row style generator", name);
+ }
+
+ private void selectCellStyleNameGenerator(String name) {
+ selectMenuPath("Component", "State", "Cell style generator", name);
+ }
+
+ @Test
+ public void testEmptyStringStyleGenerator() {
+ setDebug(true);
+ openTestURL();
+
+ selectCellStyleNameGenerator(GridBasics.CELL_STYLE_GENERATOR_EMPTY);
+ selectRowStyleNameGenerator(GridBasics.ROW_STYLE_GENERATOR_EMPTY);
+
+ assertFalse("Error notification was present",
+ isElementPresent(NotificationElement.class));
+ }
+
+ @Test
+ public void testNullStringStyleGenerator() {
+ setDebug(true);
+ openTestURL();
+
+ selectCellStyleNameGenerator(GridBasics.CELL_STYLE_GENERATOR_NULL);
+ selectRowStyleNameGenerator(GridBasics.ROW_STYLE_GENERATOR_NULL);
+
+ assertFalse("Error notification was present",
+ isElementPresent(NotificationElement.class));
+ }
+}
diff --git a/uitest/src/test/java/com/vaadin/tests/components/grid/basics/GridContentTest.java b/uitest/src/test/java/com/vaadin/tests/components/grid/basics/GridContentTest.java
index 88f2eb0b20..ba7187a5ec 100644
--- a/uitest/src/test/java/com/vaadin/tests/components/grid/basics/GridContentTest.java
+++ b/uitest/src/test/java/com/vaadin/tests/components/grid/basics/GridContentTest.java
@@ -10,8 +10,8 @@ public class GridContentTest extends GridBasicsTest {
DataObject first = getTestData().findFirst().orElse(null);
Assert.assertEquals("Text content should match row number",
first.getRowNumber().toString(),
- getGridElement().getCell(0, 4).getText());
+ getGridElement().getCell(0, 5).getText());
Assert.assertEquals("HTML content did not match", first.getHtmlString(),
- getGridElement().getCell(0, 4).getAttribute("innerHTML"));
+ getGridElement().getCell(0, 5).getAttribute("innerHTML"));
}
}