From 761c94ab2e1019f7d83d4e8d63254de1ee591d75 Mon Sep 17 00:00:00 2001 From: Teemu Suo-Anttila Date: Thu, 9 Mar 2017 09:29:51 +0200 Subject: Initial implementation of ComponentRenderer for Grid (#8743) Fixes #8622 Fixes #8623 --- server/src/main/java/com/vaadin/ui/Grid.java | 39 +++++++++++++ .../com/vaadin/ui/renderers/ComponentRenderer.java | 64 ++++++++++++++++++++++ 2 files changed, 103 insertions(+) create mode 100644 server/src/main/java/com/vaadin/ui/renderers/ComponentRenderer.java (limited to 'server/src/main') diff --git a/server/src/main/java/com/vaadin/ui/Grid.java b/server/src/main/java/com/vaadin/ui/Grid.java index 5d03825c6f..d0b908a956 100644 --- a/server/src/main/java/com/vaadin/ui/Grid.java +++ b/server/src/main/java/com/vaadin/ui/Grid.java @@ -115,6 +115,7 @@ import com.vaadin.ui.declarative.DesignContext; import com.vaadin.ui.declarative.DesignException; import com.vaadin.ui.declarative.DesignFormatter; import com.vaadin.ui.renderers.AbstractRenderer; +import com.vaadin.ui.renderers.ComponentRenderer; import com.vaadin.ui.renderers.HtmlRenderer; import com.vaadin.ui.renderers.Renderer; import com.vaadin.ui.renderers.TextRenderer; @@ -831,6 +832,7 @@ public class Grid extends AbstractListing implements HasComponents, private DescriptionGenerator descriptionGenerator; private Binding editorBinding; + private Map activeComponents = new HashMap<>(); private String userId; @@ -961,6 +963,11 @@ public class Grid extends AbstractListing implements HasComponents, V providerValue = valueProvider.apply(data); + // Make Grid track components. + if (renderer instanceof ComponentRenderer + && providerValue instanceof Component) { + addComponent(data, (Component) providerValue); + } JsonValue rendererValue = renderer.encode(providerValue); obj.put(communicationId, rendererValue); @@ -981,6 +988,38 @@ public class Grid extends AbstractListing implements HasComponents, } } + private void addComponent(T data, Component component) { + if (activeComponents.containsKey(data)) { + if (activeComponents.get(data).equals(component)) { + // Reusing old component + return; + } + removeComponent(data); + } + activeComponents.put(data, component); + addComponentToGrid(component); + } + + @Override + public void destroyData(T item) { + removeComponent(item); + } + + private void removeComponent(T item) { + Component component = activeComponents.remove(item); + if (component != null) { + removeComponentFromGrid(component); + } + } + + @Override + public void destroyAllData() { + // Make a defensive copy of keys, as the map gets cleared when + // removing components. + new HashSet<>(activeComponents.keySet()) + .forEach(this::removeComponent); + } + /** * 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 diff --git a/server/src/main/java/com/vaadin/ui/renderers/ComponentRenderer.java b/server/src/main/java/com/vaadin/ui/renderers/ComponentRenderer.java new file mode 100644 index 0000000000..1053907723 --- /dev/null +++ b/server/src/main/java/com/vaadin/ui/renderers/ComponentRenderer.java @@ -0,0 +1,64 @@ +/* + * 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.ui.renderers; + +import com.vaadin.shared.ui.grid.renderers.ComponentRendererState; +import com.vaadin.ui.Component; + +import elemental.json.Json; +import elemental.json.JsonValue; + +/** + * A renderer for presenting Components. + *

+ * Note: The use of ComponentRenderer causes the Grid to + * generate components for all items currently available in the client-side. + * This means that a number of components is always generated and sent to the + * client. Using complex structures of many nested components might be heavy to + * generate and store, which will lead to performance problems. + *

+ * Note: Components will occasionally be generated again during + * runtime e.g. when selection changes. If your component has an internal state + * that is not stored into the object, you should reuse the same component + * instances. + * + * @author Vaadin Ltd + * @since 8.1 + */ +public class ComponentRenderer extends AbstractRenderer { + + /** + * Constructor for ComponentRenderer. + */ + public ComponentRenderer() { + super(Component.class); + } + + @Override + public JsonValue encode(Component value) { + return Json.create(value.getConnectorId()); + } + + @Override + protected ComponentRendererState getState(boolean markAsDirty) { + return (ComponentRendererState) super.getState(markAsDirty); + } + + @Override + protected ComponentRendererState getState() { + return (ComponentRendererState) super.getState(); + } +} -- cgit v1.2.3