summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTeppo Kurki <teppo.kurki@vaadin.com>2015-07-02 16:37:01 +0300
committerJohannes Dahlström <johannesd@vaadin.com>2015-07-15 09:41:08 +0000
commit80058d9429940c376c63c086b1cf79848fe1a699 (patch)
tree9a7a802ead6200f64a6effe3189de57a830dcd19
parente288b0d159e4116b863836c4486a7bf289da16eb (diff)
downloadvaadin-framework-80058d9429940c376c63c086b1cf79848fe1a699.tar.gz
vaadin-framework-80058d9429940c376c63c086b1cf79848fe1a699.zip
Add row and cell description generators to Grid (#18481)
Change-Id: I940399d986eb6970df687880645fafc157dab432
-rw-r--r--client/src/com/vaadin/client/connectors/GridConnector.java40
-rw-r--r--client/src/com/vaadin/client/widgets/Grid.java22
-rw-r--r--server/src/com/vaadin/ui/Grid.java217
-rw-r--r--shared/src/com/vaadin/shared/ui/grid/GridState.java17
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java43
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridDescriptionGeneratorTest.java74
6 files changed, 380 insertions, 33 deletions
diff --git a/client/src/com/vaadin/client/connectors/GridConnector.java b/client/src/com/vaadin/client/connectors/GridConnector.java
index d42041670e..3c83fb2c24 100644
--- a/client/src/com/vaadin/client/connectors/GridConnector.java
+++ b/client/src/com/vaadin/client/connectors/GridConnector.java
@@ -31,6 +31,7 @@ import java.util.logging.Logger;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
+import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.Widget;
@@ -38,6 +39,7 @@ import com.vaadin.client.ComponentConnector;
import com.vaadin.client.ConnectorHierarchyChangeEvent;
import com.vaadin.client.DeferredWorker;
import com.vaadin.client.MouseEventDetailsBuilder;
+import com.vaadin.client.TooltipInfo;
import com.vaadin.client.communication.StateChangeEvent;
import com.vaadin.client.connectors.RpcDataSourceConnector.DetailsListener;
import com.vaadin.client.connectors.RpcDataSourceConnector.RpcDataSource;
@@ -1456,4 +1458,42 @@ public class GridConnector extends AbstractHasComponentsConnector implements
public DetailsListener getDetailsListener() {
return detailsListener;
}
+
+ @Override
+ public boolean hasTooltip() {
+ return getState().hasDescriptions || super.hasTooltip();
+ }
+
+ @Override
+ public TooltipInfo getTooltipInfo(Element element) {
+ CellReference<JsonObject> cell = getWidget().getCellReference(element);
+
+ if (cell != null) {
+ JsonObject row = cell.getRow();
+ if (row == null) {
+ return null;
+ }
+
+ Column<?, JsonObject> column = cell.getColumn();
+ if (!(column instanceof CustomGridColumn)) {
+ // Selection checkbox column
+ return null;
+ }
+ CustomGridColumn c = (CustomGridColumn) column;
+
+ JsonObject cellDescriptions = row
+ .getObject(GridState.JSONKEY_CELLDESCRIPTION);
+
+ if (cellDescriptions != null && cellDescriptions.hasKey(c.id)) {
+ return new TooltipInfo(cellDescriptions.getString(c.id));
+ } else if (row.hasKey(GridState.JSONKEY_ROWDESCRIPTION)) {
+ return new TooltipInfo(
+ row.getString(GridState.JSONKEY_ROWDESCRIPTION));
+ } else {
+ return null;
+ }
+ }
+
+ return super.getTooltipInfo(element);
+ }
}
diff --git a/client/src/com/vaadin/client/widgets/Grid.java b/client/src/com/vaadin/client/widgets/Grid.java
index 0555df3c1f..cf05e7e53a 100644
--- a/client/src/com/vaadin/client/widgets/Grid.java
+++ b/client/src/com/vaadin/client/widgets/Grid.java
@@ -8173,4 +8173,26 @@ public class Grid<T> extends ResizeComposite implements
public EventCellReference<T> getEventCell() {
return eventCell;
}
+
+ /**
+ * Returns a CellReference for the cell to which the given element belongs
+ * to.
+ *
+ * @since
+ * @param element
+ * Element to find from the cell's content.
+ * @return CellReference or <code>null</code> if cell was not found.
+ */
+ public CellReference<T> getCellReference(Element element) {
+ RowContainer container = getEscalator().findRowContainer(element);
+ if (container != null) {
+ Cell cell = container.getCell(element);
+ if (cell != null) {
+ EventCellReference<T> cellRef = new EventCellReference<T>(this);
+ cellRef.set(cell, getSectionFromContainer(container));
+ return cellRef;
+ }
+ }
+ return null;
+ }
}
diff --git a/server/src/com/vaadin/ui/Grid.java b/server/src/com/vaadin/ui/Grid.java
index f025b6e1c0..ab4236fdf0 100644
--- a/server/src/com/vaadin/ui/Grid.java
+++ b/server/src/com/vaadin/ui/Grid.java
@@ -1514,39 +1514,88 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
}
/**
- * Callback interface for generating custom style names for data rows
+ * A callback interface for generating custom style names for Grid rows.
*
* @see Grid#setRowStyleGenerator(RowStyleGenerator)
*/
public interface RowStyleGenerator extends Serializable {
/**
- * Called by Grid to generate a style name for a row
+ * Called by Grid to generate a style name for a row.
*
- * @param rowReference
- * The row to generate a style for
+ * @param row
+ * the row to generate a style for
* @return the style name to add to this row, or {@code null} to not set
* any style
*/
- public String getStyle(RowReference rowReference);
+ public String getStyle(RowReference row);
}
/**
- * Callback interface for generating custom style names for cells
+ * A callback interface for generating custom style names for Grid cells.
*
* @see Grid#setCellStyleGenerator(CellStyleGenerator)
*/
public interface CellStyleGenerator extends Serializable {
/**
- * Called by Grid to generate a style name for a column
+ * Called by Grid to generate a style name for a column.
*
- * @param cellReference
- * The cell to generate a style for
+ * @param cell
+ * the cell to generate a style for
* @return the style name to add to this cell, or {@code null} to not
* set any style
*/
- public String getStyle(CellReference cellReference);
+ public String getStyle(CellReference cell);
+ }
+
+ /**
+ * A callback interface for generating optional descriptions (tooltips) for
+ * Grid rows. If a description is generated for a row, it is used for all
+ * the cells in the row for which a {@link CellDescriptionGenerator cell
+ * description} is not generated.
+ *
+ * @see Grid#setRowDescriptionGenerator(CellDescriptionGenerator)
+ *
+ * @since
+ */
+ public interface RowDescriptionGenerator extends Serializable {
+
+ /**
+ * Called by Grid to generate a description (tooltip) for a row. The
+ * description may contain HTML which is rendered directly; if this is
+ * not desired the returned string must be escaped by the implementing
+ * method.
+ *
+ * @param row
+ * the row to generate a description for
+ * @return the row description or {@code null} for no description
+ */
+ public String getDescription(RowReference row);
+ }
+
+ /**
+ * A callback interface for generating optional descriptions (tooltips) for
+ * Grid cells. If a cell has both a {@link RowDescriptionGenerator row
+ * description} and a cell description, the latter has precedence.
+ *
+ * @see Grid#setCellDescriptionGenerator(CellDescriptionGenerator)
+ *
+ * @since
+ */
+ public interface CellDescriptionGenerator extends Serializable {
+
+ /**
+ * Called by Grid to generate a description (tooltip) for a cell. The
+ * description may contain HTML which is rendered directly; if this is
+ * not desired the returned string must be escaped by the implementing
+ * method.
+ *
+ * @param cell
+ * the cell to generate a description for
+ * @return the cell description or {@code null} for no description
+ */
+ public String getDescription(CellReference cell);
}
/**
@@ -1555,51 +1604,83 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
*/
private class RowDataGenerator implements DataGenerator {
+ private void put(String key, String value, JsonObject object) {
+ if (value != null && !value.isEmpty()) {
+ object.put(key, value);
+ }
+ }
+
@Override
public void generateData(Object itemId, Item item, JsonObject rowData) {
- RowReference r = new RowReference(Grid.this);
- r.set(itemId);
+ RowReference row = new RowReference(Grid.this);
+ row.set(itemId);
if (rowStyleGenerator != null) {
- String style = rowStyleGenerator.getStyle(r);
- if (style != null && !style.isEmpty()) {
- rowData.put(GridState.JSONKEY_ROWSTYLE, style);
- }
+ String style = rowStyleGenerator.getStyle(row);
+ put(GridState.JSONKEY_ROWSTYLE, style, rowData);
+ }
+
+ if (rowDescriptionGenerator != null) {
+ String description = rowDescriptionGenerator
+ .getDescription(row);
+ put(GridState.JSONKEY_ROWDESCRIPTION, description, rowData);
+
}
JsonObject cellStyles = Json.createObject();
JsonObject cellData = Json.createObject();
- for (Column column : getColumns()) {
- Object propertyId = column.getPropertyId();
- String columnId = columnKeys.key(propertyId);
+ JsonObject cellDescriptions = Json.createObject();
- cellData.put(columnId, getRendererData(column, item));
+ CellReference cell = new CellReference(row);
- if (cellStyleGenerator != null) {
- CellReference c = new CellReference(r);
- c.set(propertyId);
+ for (Column column : getColumns()) {
+ cell.set(column.getPropertyId());
- String style = cellStyleGenerator.getStyle(c);
- if (style != null && !style.isEmpty()) {
- cellStyles.put(columnId, style);
- }
- }
+ writeData(cell, cellData);
+ writeStyles(cell, cellStyles);
+ writeDescriptions(cell, cellDescriptions);
+ }
+
+ if (cellDescriptionGenerator != null
+ && cellDescriptions.keys().length > 0) {
+ rowData.put(GridState.JSONKEY_CELLDESCRIPTION, cellDescriptions);
}
if (cellStyleGenerator != null && cellStyles.keys().length > 0) {
rowData.put(GridState.JSONKEY_CELLSTYLES, cellStyles);
}
+
rowData.put(GridState.JSONKEY_DATA, cellData);
}
- private JsonValue getRendererData(Column column, Item item) {
+ private void writeStyles(CellReference cell, JsonObject styles) {
+ if (cellStyleGenerator != null) {
+ String style = cellStyleGenerator.getStyle(cell);
+ put(columnKeys.key(cell.getPropertyId()), style, styles);
+ }
+ }
+
+ private void writeDescriptions(CellReference cell,
+ JsonObject descriptions) {
+ if (cellDescriptionGenerator != null) {
+ String description = cellDescriptionGenerator
+ .getDescription(cell);
+ put(columnKeys.key(cell.getPropertyId()), description,
+ descriptions);
+ }
+ }
+
+ private void writeData(CellReference cell, JsonObject data) {
+ Column column = getColumn(cell.getPropertyId());
Converter<?, ?> converter = column.getConverter();
- Object propertyId = column.getPropertyId();
- Object modelValue = item.getItemProperty(propertyId).getValue();
Renderer<?> renderer = column.getRenderer();
- return AbstractRenderer.encodeValue(modelValue, renderer,
- converter, getLocale());
+ Item item = cell.getItem();
+ Object modelValue = item.getItemProperty(cell.getPropertyId())
+ .getValue();
+
+ data.put(columnKeys.key(cell.getPropertyId()), AbstractRenderer
+ .encodeValue(modelValue, renderer, converter, getLocale()));
}
}
@@ -3781,6 +3862,9 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
private CellStyleGenerator cellStyleGenerator;
private RowStyleGenerator rowStyleGenerator;
+ private CellDescriptionGenerator cellDescriptionGenerator;
+ private RowDescriptionGenerator rowDescriptionGenerator;
+
/**
* <code>true</code> if Grid is using the internal IndexedContainer created
* in Grid() constructor, or <code>false</code> if the user has set their
@@ -5760,6 +5844,73 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
}
/**
+ * Sets the {@code CellDescriptionGenerator} instance for generating
+ * optional descriptions (tooltips) for individual Grid cells. If a
+ * {@link RowDescriptionGenerator} is also set, the row description it
+ * generates is displayed for cells for which {@code generator} returns
+ * null.
+ *
+ * @param generator
+ * the description generator to use or {@code null} to remove a
+ * previously set generator if any
+ *
+ * @see #setRowDescriptionGenerator(RowDescriptionGenerator)
+ *
+ * @since
+ */
+ public void setCellDescriptionGenerator(CellDescriptionGenerator generator) {
+ cellDescriptionGenerator = generator;
+ getState().hasDescriptions = (generator != null || rowDescriptionGenerator != null);
+ datasourceExtension.refreshCache();
+ }
+
+ /**
+ * Returns the {@code CellDescriptionGenerator} instance used to generate
+ * descriptions (tooltips) for Grid cells.
+ *
+ * @return the description generator or {@code null} if no generator is set
+ *
+ * @since
+ */
+ public CellDescriptionGenerator getCellDescriptionGenerator() {
+ return cellDescriptionGenerator;
+ }
+
+ /**
+ * Sets the {@code RowDescriptionGenerator} instance for generating optional
+ * descriptions (tooltips) for Grid rows. If a
+ * {@link CellDescriptionGenerator} is also set, the row description
+ * generated by {@code generator} is used for cells for which the cell
+ * description generator returns null.
+ *
+ *
+ * @param generator
+ * the description generator to use or {@code null} to remove a
+ * previously set generator if any
+ *
+ * @see #setCellDescriptionGenerator(CellDescriptionGenerator)
+ *
+ * @since
+ */
+ public void setRowDescriptionGenerator(RowDescriptionGenerator generator) {
+ rowDescriptionGenerator = generator;
+ getState().hasDescriptions = (generator != null || cellDescriptionGenerator != null);
+ datasourceExtension.refreshCache();
+ }
+
+ /**
+ * Returns the {@code RowDescriptionGenerator} instance used to generate
+ * descriptions (tooltips) for Grid rows
+ *
+ * @return the description generator or {@code} null if no generator is set
+ *
+ * @since
+ */
+ public RowDescriptionGenerator getRowDescriptionGenerator() {
+ return rowDescriptionGenerator;
+ }
+
+ /**
* Sets the style generator that is used for generating styles for cells
*
* @param cellStyleGenerator
diff --git a/shared/src/com/vaadin/shared/ui/grid/GridState.java b/shared/src/com/vaadin/shared/ui/grid/GridState.java
index c455ffe23b..0d0a5d3e9f 100644
--- a/shared/src/com/vaadin/shared/ui/grid/GridState.java
+++ b/shared/src/com/vaadin/shared/ui/grid/GridState.java
@@ -103,6 +103,20 @@ public class GridState extends TabIndexState {
public static final String JSONKEY_CELLSTYLES = "cs";
/**
+ * The key in which a row's description can be found
+ *
+ * @see com.vaadin.shared.data.DataProviderRpc#setRowData(int, String)
+ */
+ public static final String JSONKEY_ROWDESCRIPTION = "rd";
+
+ /**
+ * The key in which a cell's description can be found
+ *
+ * @see com.vaadin.shared.data.DataProviderRpc#setRowData(int, String)
+ */
+ public static final String JSONKEY_CELLDESCRIPTION = "cd";
+
+ /**
* The key that tells whether details are visible for the row.
*
* @since 7.5.0
@@ -160,6 +174,9 @@ public class GridState extends TabIndexState {
@DelegateToWidget
public boolean editorBuffered = true;
+ /** Whether rows and/or cells have generated descriptions (tooltips) */
+ public boolean hasDescriptions;
+
/** The caption for the save button in the editor */
@DelegateToWidget
public String editorSaveCaption = GridConstants.DEFAULT_SAVE_CAPTION;
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 3154fd2a85..33a54b1c9a 100644
--- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java
@@ -52,6 +52,7 @@ import com.vaadin.ui.Component;
import com.vaadin.ui.CssLayout;
import com.vaadin.ui.Field;
import com.vaadin.ui.Grid;
+import com.vaadin.ui.Grid.CellDescriptionGenerator;
import com.vaadin.ui.Grid.CellReference;
import com.vaadin.ui.Grid.CellStyleGenerator;
import com.vaadin.ui.Grid.Column;
@@ -68,6 +69,7 @@ import com.vaadin.ui.Grid.FooterCell;
import com.vaadin.ui.Grid.HeaderCell;
import com.vaadin.ui.Grid.HeaderRow;
import com.vaadin.ui.Grid.MultiSelectionModel;
+import com.vaadin.ui.Grid.RowDescriptionGenerator;
import com.vaadin.ui.Grid.RowReference;
import com.vaadin.ui.Grid.RowStyleGenerator;
import com.vaadin.ui.Grid.SelectionMode;
@@ -130,6 +132,27 @@ public class GridBasicFeatures extends AbstractComponentTest<Grid> {
}
};
+ private RowDescriptionGenerator rowDescriptionGenerator = new RowDescriptionGenerator() {
+
+ @Override
+ public String getDescription(RowReference row) {
+ return "Row tooltip for row " + row.getItemId();
+ }
+ };
+
+ private CellDescriptionGenerator cellDescriptionGenerator = new CellDescriptionGenerator() {
+
+ @Override
+ public String getDescription(CellReference cell) {
+ if ("Column 0".equals(cell.getPropertyId())) {
+ return "Cell tooltip for row " + cell.getItemId()
+ + ", column 0";
+ } else {
+ return null;
+ }
+ }
+ };
+
private ItemClickListener editorOpeningItemClickListener = new ItemClickListener() {
@Override
@@ -629,6 +652,25 @@ public class GridBasicFeatures extends AbstractComponentTest<Grid> {
}
});
+ createBooleanAction("Row description generator", "State", false,
+ new Command<Grid, Boolean>() {
+
+ @Override
+ public void execute(Grid c, Boolean value, Object data) {
+ c.setRowDescriptionGenerator(value ? rowDescriptionGenerator
+ : null);
+ }
+ });
+
+ createBooleanAction("Cell description generator", "State", false,
+ new Command<Grid, Boolean>() {
+ @Override
+ public void execute(Grid c, Boolean value, Object data) {
+ c.setCellDescriptionGenerator(value ? cellDescriptionGenerator
+ : null);
+ }
+ });
+
LinkedHashMap<String, Integer> frozenOptions = new LinkedHashMap<String, Integer>();
for (int i = -1; i <= COLUMNS; i++) {
frozenOptions.put(String.valueOf(i), Integer.valueOf(i));
@@ -673,6 +715,7 @@ public class GridBasicFeatures extends AbstractComponentTest<Grid> {
}
});
+
createBooleanAction("EditorOpeningItemClickListener", "State", false,
new Command<Grid, Boolean>() {
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridDescriptionGeneratorTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridDescriptionGeneratorTest.java
new file mode 100644
index 0000000000..ed712361a6
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridDescriptionGeneratorTest.java
@@ -0,0 +1,74 @@
+/*
+ * 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;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+import org.openqa.selenium.By;
+
+public class GridDescriptionGeneratorTest extends GridBasicFeaturesTest {
+
+ @Test
+ public void testCellDescription() {
+ openTestURL();
+ selectMenuPath("Component", "State", "Cell description generator");
+
+ getGridElement().getCell(1, 0).showTooltip();
+ String tooltipText = findElement(By.className("v-tooltip-text"))
+ .getText();
+ assertEquals("Tooltip text", "Cell tooltip for row 1, column 0",
+ tooltipText);
+
+ getGridElement().getCell(1, 1).showTooltip();
+ assertTrue("Tooltip should not be present in cell (1, 1) ",
+ findElement(By.className("v-tooltip-text")).getText().isEmpty());
+ }
+
+ @Test
+ public void testRowDescription() {
+ openTestURL();
+ selectMenuPath("Component", "State", "Row description generator");
+
+ getGridElement().getCell(5, 3).showTooltip();
+ String tooltipText = findElement(By.className("v-tooltip-text"))
+ .getText();
+ assertEquals("Tooltip text", "Row tooltip for row 5", tooltipText);
+
+ getGridElement().getCell(15, 3).showTooltip();
+ tooltipText = findElement(By.className("v-tooltip-text")).getText();
+ assertEquals("Tooltip text", "Row tooltip for row 15", tooltipText);
+ }
+
+ @Test
+ public void testRowAndCellDescription() {
+ openTestURL();
+ selectMenuPath("Component", "State", "Row description generator");
+ selectMenuPath("Component", "State", "Cell description generator");
+
+ getGridElement().getCell(5, 0).showTooltip();
+ String tooltipText = findElement(By.className("v-tooltip-text"))
+ .getText();
+ assertEquals("Tooltip text", "Cell tooltip for row 5, column 0",
+ tooltipText);
+
+ getGridElement().getCell(5, 3).showTooltip();
+ tooltipText = findElement(By.className("v-tooltip-text")).getText();
+ assertEquals("Tooltip text", "Row tooltip for row 5", tooltipText);
+ }
+
+}