summaryrefslogtreecommitdiffstats
path: root/server/src/com/vaadin/ui/Grid.java
diff options
context:
space:
mode:
Diffstat (limited to 'server/src/com/vaadin/ui/Grid.java')
-rw-r--r--server/src/com/vaadin/ui/Grid.java147
1 files changed, 141 insertions, 6 deletions
diff --git a/server/src/com/vaadin/ui/Grid.java b/server/src/com/vaadin/ui/Grid.java
index f7d49e6419..af89064411 100644
--- a/server/src/com/vaadin/ui/Grid.java
+++ b/server/src/com/vaadin/ui/Grid.java
@@ -31,6 +31,7 @@ import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
@@ -52,6 +53,7 @@ import com.vaadin.data.Container.PropertySetChangeEvent;
import com.vaadin.data.Container.PropertySetChangeListener;
import com.vaadin.data.Container.PropertySetChangeNotifier;
import com.vaadin.data.Container.Sortable;
+import com.vaadin.data.DataGenerator;
import com.vaadin.data.Item;
import com.vaadin.data.Property;
import com.vaadin.data.RpcDataProviderExtension;
@@ -1548,6 +1550,60 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
}
/**
+ * Class for generating all row and cell related data for the essential
+ * parts of Grid.
+ */
+ private class RowDataGenerator implements DataGenerator {
+
+ @Override
+ public void generateData(Object itemId, Item item, JsonObject rowData) {
+ RowReference r = new RowReference(Grid.this);
+ r.set(itemId);
+
+ if (rowStyleGenerator != null) {
+ String style = rowStyleGenerator.getStyle(r);
+ if (style != null && !style.isEmpty()) {
+ rowData.put(GridState.JSONKEY_ROWSTYLE, style);
+ }
+ }
+
+ JsonObject cellStyles = Json.createObject();
+ JsonObject cellData = Json.createObject();
+ for (Column column : getColumns()) {
+ Object propertyId = column.getPropertyId();
+ String columnId = columnKeys.key(propertyId);
+
+ cellData.put(columnId, getRendererData(column, item));
+
+ if (cellStyleGenerator != null) {
+ CellReference c = new CellReference(r);
+ c.set(propertyId);
+
+ String style = cellStyleGenerator.getStyle(c);
+ if (style != null && !style.isEmpty()) {
+ cellStyles.put(columnId, style);
+ }
+ }
+ }
+
+ 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) {
+ 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());
+ }
+ }
+
+ /**
* Abstract base class for Grid header and footer sections.
*
* @param <ROWTYPE>
@@ -3462,10 +3518,67 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
return JsonCodec.encode(value, null, type,
getUI().getConnectorTracker()).getEncodedValue();
}
+
+ /**
+ * Converts and encodes the given data model property value using the
+ * given converter and renderer. This method is public only for testing
+ * purposes.
+ *
+ * @param renderer
+ * the renderer to use
+ * @param converter
+ * the converter to use
+ * @param modelValue
+ * the value to convert and encode
+ * @param locale
+ * the locale to use in conversion
+ * @return an encoded value ready to be sent to the client
+ */
+ public static <T> JsonValue encodeValue(Object modelValue,
+ Renderer<T> renderer, Converter<?, ?> converter, Locale locale) {
+ Class<T> presentationType = renderer.getPresentationType();
+ T presentationValue;
+
+ if (converter == null) {
+ try {
+ presentationValue = presentationType.cast(modelValue);
+ } catch (ClassCastException e) {
+ if (presentationType == String.class) {
+ // If there is no converter, just fallback to using
+ // toString(). modelValue can't be null as
+ // Class.cast(null) will always succeed
+ presentationValue = (T) modelValue.toString();
+ } else {
+ throw new Converter.ConversionException(
+ "Unable to convert value of type "
+ + modelValue.getClass().getName()
+ + " to presentation type "
+ + presentationType.getName()
+ + ". No converter is set and the types are not compatible.");
+ }
+ }
+ } else {
+ assert presentationType.isAssignableFrom(converter
+ .getPresentationType());
+ @SuppressWarnings("unchecked")
+ Converter<T, Object> safeConverter = (Converter<T, Object>) converter;
+ presentationValue = safeConverter
+ .convertToPresentation(modelValue,
+ safeConverter.getPresentationType(), locale);
+ }
+
+ JsonValue encodedValue = renderer.encode(presentationValue);
+
+ return encodedValue;
+ }
}
/**
* An abstract base class for server-side Grid extensions.
+ * <p>
+ * Note: If the extension is an instance of {@link DataGenerator} it will
+ * automatically register itself to {@link RpcDataProviderExtension} of
+ * extended Grid. On remove this registration is automatically removed.
*
* @since 7.5
*/
@@ -3490,6 +3603,26 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
extend(grid);
}
+ @Override
+ protected void extend(AbstractClientConnector target) {
+ super.extend(target);
+
+ if (this instanceof DataGenerator) {
+ getParentGrid().datasourceExtension
+ .addDataGenerator((DataGenerator) this);
+ }
+ }
+
+ @Override
+ public void remove() {
+ if (this instanceof DataGenerator) {
+ getParentGrid().datasourceExtension
+ .removeDataGenerator((DataGenerator) this);
+ }
+
+ super.remove();
+ }
+
/**
* Gets the item id for a row key.
* <p>
@@ -3531,9 +3664,14 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
if (getParent() instanceof Grid) {
Grid grid = (Grid) getParent();
return grid;
+ } else if (getParent() == null) {
+ throw new IllegalStateException(
+ "Renderer is not attached to any parent");
} else {
throw new IllegalStateException(
- "Renderers can be used only with Grid");
+ "Renderers can be used only with Grid. Extended "
+ + getParent().getClass().getSimpleName()
+ + " instead");
}
}
}
@@ -4153,7 +4291,8 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
}
datasourceExtension = new RpcDataProviderExtension(container);
- datasourceExtension.extend(this, columnKeys);
+ datasourceExtension.extend(this);
+ datasourceExtension.addDataGenerator(new RowDataGenerator());
detailComponentManager = datasourceExtension
.getDetailComponentManager();
@@ -5620,8 +5759,6 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
*/
public void setCellStyleGenerator(CellStyleGenerator cellStyleGenerator) {
this.cellStyleGenerator = cellStyleGenerator;
- getState().hasCellStyleGenerator = (cellStyleGenerator != null);
-
datasourceExtension.refreshCache();
}
@@ -5644,8 +5781,6 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
*/
public void setRowStyleGenerator(RowStyleGenerator rowStyleGenerator) {
this.rowStyleGenerator = rowStyleGenerator;
- getState().hasRowStyleGenerator = (rowStyleGenerator != null);
-
datasourceExtension.refreshCache();
}