From de8cf4f7d7035bdc8d07ef0b03253ef44485d29c Mon Sep 17 00:00:00 2001 From: Antti Villberg Date: Mon, 3 Apr 2017 10:25:30 +0300 Subject: [PATCH] Support SVG generation from scenegraph refs #7054 Change-Id: Ide69219fee786bd19ccf447c227c2424d9cabdc2 --- .../diagram/adapter/CompositeImage.java | 2 + .../diagram/participant/ElementPainter.java | 2 + .../META-INF/MANIFEST.MF | 3 +- .../scl/Simantics/Scenegraph.scl | 4 +- .../org/simantics/modeling/SCLScenegraph.java | 296 +++++++++++++++++- .../org/simantics/scenegraph/g2d/G2DNode.java | 5 + .../scenegraph/g2d/G2DParentNode.java | 11 + .../scenegraph/g2d/G2DRenderingHints.java | 28 +- .../simantics/scenegraph/g2d/IG2DNode.java | 8 + .../scenegraph/g2d/IG2DNodeVisitor.java | 23 ++ .../scenegraph/g2d/nodes/ConnectionNode.java | 12 + .../scenegraph/g2d/nodes/SVGNode.java | 7 + .../g2d/nodes/SingleElementNode.java | 18 ++ .../scenegraph/g2d/nodes/UnboundedNode.java | 9 + 14 files changed, 416 insertions(+), 12 deletions(-) create mode 100644 bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/IG2DNodeVisitor.java diff --git a/bundles/org.simantics.diagram/src/org/simantics/diagram/adapter/CompositeImage.java b/bundles/org.simantics.diagram/src/org/simantics/diagram/adapter/CompositeImage.java index 93957f069..98f229b91 100644 --- a/bundles/org.simantics.diagram/src/org/simantics/diagram/adapter/CompositeImage.java +++ b/bundles/org.simantics.diagram/src/org/simantics/diagram/adapter/CompositeImage.java @@ -18,6 +18,7 @@ import java.util.EnumSet; import java.util.List; import org.simantics.g2d.element.ElementClass; +import org.simantics.g2d.element.ElementHints; import org.simantics.g2d.element.ElementUtils; import org.simantics.g2d.element.IElement; import org.simantics.g2d.element.SceneGraphNodeKey; @@ -140,6 +141,7 @@ public class CompositeImage implements Image { SingleElementNode holder = node.getOrCreateNode(ElementUtils.generateNodeId(e), SingleElementNode.class); //SingleElementNode holder = parent.getOrCreateNode(ElementUtils.generateNodeId(e), SingleElementNode.class); holder.setZIndex(++zIndex); + holder.setKey(e.getHint(ElementHints.KEY_OBJECT)); List nodeHandlers = ec.getItemsByClass(SceneGraph.class); for(SceneGraph n : nodeHandlers) { diff --git a/bundles/org.simantics.g2d/src/org/simantics/g2d/diagram/participant/ElementPainter.java b/bundles/org.simantics.g2d/src/org/simantics/g2d/diagram/participant/ElementPainter.java index 1eb15f61c..d69ef69c6 100644 --- a/bundles/org.simantics.g2d/src/org/simantics/g2d/diagram/participant/ElementPainter.java +++ b/bundles/org.simantics.g2d/src/org/simantics/g2d/diagram/participant/ElementPainter.java @@ -557,6 +557,7 @@ public class ElementPainter extends AbstractDiagramParticipant implements Compos ConnectionNode holder = e.getHint(sgKey); if (holder == null) { holder = parentNode.addNode(ElementUtils.generateNodeId(e), ConnectionNode.class); + holder.setKey(e.getHint(ElementHints.KEY_OBJECT)); holder.setTransferableProvider(new ElementTransferableProvider(getContext(), e)); e.setHint(sgKey, holder); holder.setZIndex(parentNode.getNodeCount() + 1); @@ -567,6 +568,7 @@ public class ElementPainter extends AbstractDiagramParticipant implements Compos SingleElementNode holder = e.getHint(sgKey); if (holder == null) { holder = parentNode.addNode(ElementUtils.generateNodeId(e), SingleElementNode.class); + holder.setKey(e.getHint(ElementHints.KEY_OBJECT)); holder.setTransferableProvider(new ElementTransferableProvider(getContext(), e)); e.setHint(sgKey, holder); holder.setZIndex(parentNode.getNodeCount() + 1); diff --git a/bundles/org.simantics.modeling/META-INF/MANIFEST.MF b/bundles/org.simantics.modeling/META-INF/MANIFEST.MF index 5245ed47e..7f81e56f2 100644 --- a/bundles/org.simantics.modeling/META-INF/MANIFEST.MF +++ b/bundles/org.simantics.modeling/META-INF/MANIFEST.MF @@ -37,7 +37,8 @@ Require-Bundle: org.simantics.simulation;bundle-version="1.0.0", org.simantics.scl.db;bundle-version="0.1.3", org.simantics.selectionview.ontology;bundle-version="1.2.0", org.simantics.scl.ui;bundle-version="0.5.0", - org.slf4j.api + org.slf4j.api, + org.apache.batik Export-Package: org.simantics.modeling, org.simantics.modeling.actions, org.simantics.modeling.adapters, diff --git a/bundles/org.simantics.modeling/scl/Simantics/Scenegraph.scl b/bundles/org.simantics.modeling/scl/Simantics/Scenegraph.scl index fa1d2193f..5e0e83075 100644 --- a/bundles/org.simantics.modeling/scl/Simantics/Scenegraph.scl +++ b/bundles/org.simantics.modeling/scl/Simantics/Scenegraph.scl @@ -51,12 +51,14 @@ importJava "org.simantics.modeling.SCLScenegraph" where editNodeText :: ICanvasContext -> String -> String -> String -> String copyPaste :: ICanvasContext -> ICanvasContext -> [Resource] -> Boolean + + renderSVG :: ICanvasContext -> String getSceneGraphProvider :: Diagram -> ICanvasSceneGraphProvider getSceneGraphProvider diagram = do diagramName = syncRead(\() -> getSafeName diagram) diagramRVI = "/" + diagramName - model = syncRead(\() -> getPossibleModel diagram) + model = syncRead(\() -> fromJust $ possibleIndexRoot diagram) composite = syncRead(\() -> compositeToDiagram' diagram) getICanvasSceneGraphProvider model composite diagramRVI diff --git a/bundles/org.simantics.modeling/src/org/simantics/modeling/SCLScenegraph.java b/bundles/org.simantics.modeling/src/org/simantics/modeling/SCLScenegraph.java index 33d7f0629..358d50fb4 100644 --- a/bundles/org.simantics.modeling/src/org/simantics/modeling/SCLScenegraph.java +++ b/bundles/org.simantics.modeling/src/org/simantics/modeling/SCLScenegraph.java @@ -1,10 +1,28 @@ package org.simantics.modeling; +import java.awt.Dimension; +import java.awt.RenderingHints; +import java.awt.RenderingHints.Key; +import java.awt.geom.AffineTransform; +import java.awt.geom.Rectangle2D; +import java.io.ByteArrayOutputStream; +import java.io.OutputStreamWriter; import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; import java.util.List; import java.util.Set; +import java.util.UUID; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.apache.batik.dom.GenericDOMImplementation; +import org.apache.batik.svggen.SVGGeneratorContext; +import org.apache.batik.svggen.SVGGraphics2D; import org.simantics.db.Resource; import org.simantics.db.exception.DatabaseException; import org.simantics.diagram.elements.DiagramNodeUtil; @@ -20,7 +38,10 @@ import org.simantics.g2d.scenegraph.ICanvasSceneGraphProvider; import org.simantics.g2d.utils.CanvasUtils; import org.simantics.scenegraph.ParentNode; import org.simantics.scenegraph.g2d.G2DParentNode; +import org.simantics.scenegraph.g2d.G2DRenderingHints; import org.simantics.scenegraph.g2d.G2DSceneGraph; +import org.simantics.scenegraph.g2d.IG2DNode; +import org.simantics.scenegraph.g2d.IG2DNodeVisitor; import org.simantics.scenegraph.g2d.events.command.Commands; import org.simantics.scenegraph.g2d.nodes.BackgroundNode; import org.simantics.scenegraph.g2d.nodes.BoundsNode; @@ -28,13 +49,23 @@ import org.simantics.scenegraph.g2d.nodes.ConnectionNode; import org.simantics.scenegraph.g2d.nodes.DataNode; import org.simantics.scenegraph.g2d.nodes.DecorationSVGNode; import org.simantics.scenegraph.g2d.nodes.NavigationNode; +import org.simantics.scenegraph.g2d.nodes.SVGNode; import org.simantics.scenegraph.g2d.nodes.SingleElementNode; +import org.simantics.scenegraph.g2d.nodes.spatial.RTreeNode; import org.simantics.scenegraph.utils.NodeUtil; import org.simantics.trend.impl.ItemNode; import org.simantics.utils.threads.ThreadUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.DOMImplementation; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; public class SCLScenegraph { - + + private static final Logger LOGGER = LoggerFactory.getLogger(SCLScenegraph.class); + public static ICanvasSceneGraphProvider getICanvasSceneGraphProvider(Resource model, Resource diagram, String diagramRVI) throws DatabaseException, InterruptedException { ICanvasSceneGraphProvider provider = DiagramNodeUtil.loadSceneGraphProvider(model, diagram, diagramRVI); return provider; @@ -44,13 +75,6 @@ public class SCLScenegraph { provider.dispose(); } - //public static Resource getDiagramRuntime(Resource ) - - -// public static String getNodeTransform(ICanvasContext ctx, String name) throws DatabaseException, InterruptedException { -// return getNodeTransform(ctx, name); -// } - public static String getNodeTransform(ICanvasContext ctx, String name) { Set texts = NodeUtil.collectNodes(ctx.getSceneGraph(), TextNode.class); @@ -234,7 +258,7 @@ public class SCLScenegraph { } } - public static boolean copyPaste (final ICanvasContext source_ctx, final ICanvasContext target_ctx, List modules) throws DatabaseException { + public static boolean copyPaste (final ICanvasContext source_ctx, final ICanvasContext target_ctx, List modules) throws DatabaseException { IDiagram idiagram = source_ctx.getDefaultHintContext().getHint(DiagramHints.KEY_DIAGRAM); @@ -286,5 +310,259 @@ public class SCLScenegraph { return true; } + static class Generator extends SVGGraphics2D { + + int elemLevel = 0; + String newElementId = null; + ArrayList elements = new ArrayList(); + + public static final String svgNS = "http://www.w3.org/2000/svg"; + + public Generator(SVGGeneratorContext ctx, boolean joku) { + super(ctx, joku); + } + + public Generator(Document document) { + super(document); + } + + @Override + public Element getRoot() { + Element root = super.getRoot(); + for(Element e : elements) { + root.appendChild(e); + } + return root; + } + + @Override + public void setRenderingHint(Key arg0, Object arg1) { + if(G2DRenderingHints.KEY_BEGIN_ELEMENT == arg0) { + elemLevel++; + } + if(G2DRenderingHints.KEY_ELEMENT_ID == arg0) { + if(arg1 != null) + newElementId = arg1.toString(); + else + newElementId = UUID.randomUUID().toString(); + } + if(G2DRenderingHints.KEY_END_ELEMENT == arg0) { + elemLevel--; + if(elemLevel == 0) { + Element group = getDOMFactory().createElement(SVG_G_TAG); + //Element group = getDOMFactory().createElementNS(SVG_NAMESPACE_URI, SVG_G_TAG); + group.setAttributeNS(null, "id", newElementId); + group.setAttributeNS(null, "class", arg1.toString()); + getRoot(group); + elements.add(group); + } + } + super.setRenderingHint(arg0, arg1); + } + + } + + public static Element renderSVGNode(IG2DNode node) { + + // Get a DOMImplementation. + DOMImplementation domImpl = GenericDOMImplementation.getDOMImplementation(); + + // Create an instance of org.w3c.dom.Document. + String svgNS = "http://www.w3.org/2000/svg"; + Document document = domImpl.createDocument(svgNS, "svg", null); + + SVGGeneratorContext ctx = SVGGeneratorContext.createDefault(document); + ctx.setComment(null); + + // Create an instance of the SVG Generator. + SVGGraphics2D svgGenerator = new Generator(ctx, false); + + try { + + svgGenerator.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + svgGenerator.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); + svgGenerator.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + + node.render(svgGenerator); + + } catch (Throwable t) { + LOGGER.error("Problems rendering scene graph to SVG", t); + } + + return svgGenerator.getRoot(); + } + + public static String printSVGDocument(Element doce) { + + StringBuilder result = new StringBuilder(); + + NodeList nl = doce.getChildNodes(); + + for(int i=0;i"); + + IG2DNodeVisitor visitor = new IG2DNodeVisitor() { + + int indent = 0; + + HashMap enters = new HashMap<>(); + + @Override + public void enter(IG2DNode node) { + indent++; + if(node instanceof ConnectionNode) { + Element doc = renderSVGNode((IG2DNode)node); + String svg = printSVGDocument(doc); + b.append(svg); + } else if (node instanceof SVGNode) { + SVGNode svg = (SVGNode)node; + b.append(svg.getSVGText()); + } else if (node instanceof G2DParentNode) { + AffineTransform at = node.getTransform(); + if(node instanceof SingleElementNode) { + SingleElementNode sen = (SingleElementNode)node; + if(sen.getKey() != null) { + String key = sen.getKey().toString(); + b.append("\n"); + } + } + if(!at.isIdentity()) { + if(at.getScaleX() == 1.0 && at.getScaleY() == 1.0 && at.getShearX() == 0.0 && at.getShearY() == 0.0) { + String m = "translate(" + at.getTranslateX() + " " + at.getTranslateY() + ")"; + b.append("\n"); + } else { + double[] ds = new double[6]; + at.getMatrix(ds); + String m = "matrix(" + ds[0] + " " + ds[1] + " " + ds[2] + " " + ds[3] + " " + ds[4] + " " + ds[5] + ")"; + b.append("\n"); + } + } + } + + enters.put(node, b.length()); + + } + + @Override + public void leave(IG2DNode node) { + if(node instanceof ConnectionNode || node instanceof SVGNode) { + // We are done + } else if (node instanceof G2DParentNode) { + AffineTransform at = node.getTransform(); + if(!at.isIdentity()) { + b.append(""); + } + if(node instanceof SingleElementNode) { + SingleElementNode sen = (SingleElementNode)node; + if(sen.getKey() != null) { + int enterLength = enters.get(node); + if(b.length() == enterLength) { + Element doc = renderSVGNode((IG2DNode)node); + String svg = printSVGDocument(doc); + b.append(svg); + } + b.append(""); + } + } + } + indent --; + } + + }; + sg.accept(visitor); + + } catch (Throwable t) { + LOGGER.error("Problems rendering canvas context to SVG", t); + } + + b.append(""); + //System.err.println(" == FINAL RESULT == "); + //System.err.println(b); + return b.toString(); + + } + } \ No newline at end of file diff --git a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/G2DNode.java b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/G2DNode.java index cf4fe0b30..b39d7a058 100644 --- a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/G2DNode.java +++ b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/G2DNode.java @@ -395,5 +395,10 @@ public abstract class G2DNode extends Node implements IG2DNode { if (rootPane != null) rootPane.setCursor(cursor); } + + public void accept(IG2DNodeVisitor visitor) { + visitor.enter(this); + visitor.leave(this); + } } diff --git a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/G2DParentNode.java b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/G2DParentNode.java index 231b616e2..838eb893e 100644 --- a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/G2DParentNode.java +++ b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/G2DParentNode.java @@ -122,6 +122,17 @@ public class G2DParentNode extends ParentNode implements IG2DNode, Ini g2d.setTransform(ot); } + @Override + public void accept(IG2DNodeVisitor visitor) { + visitor.enter(this); + for (IG2DNode node : getSortedNodes()) { + if (node.validate()) { + node.accept(visitor); + } + } + visitor.leave(this); + } + /** * Return the IDs of the children of this node in ascending Z order. This * method will always allocate a new result list and sort it. To get the IDs diff --git a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/G2DRenderingHints.java b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/G2DRenderingHints.java index 00c7a6d0c..0f1803e2d 100644 --- a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/G2DRenderingHints.java +++ b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/G2DRenderingHints.java @@ -12,8 +12,8 @@ package org.simantics.scenegraph.g2d; import java.awt.Component; -import java.awt.RenderingHints.Key; import java.awt.geom.Rectangle2D; +import java.util.Map; /** * @author Tuukka Lehtonen @@ -21,6 +21,32 @@ import java.awt.geom.Rectangle2D; */ public final class G2DRenderingHints { + public static final Key KEY_BEGIN_ELEMENT = new G2DRenderingHints.Key(0); + public static final Key KEY_END_ELEMENT = new G2DRenderingHints.Key(1); + public static final Key KEY_ELEMENT_ID = new G2DRenderingHints.Key(2); + + public static class Key extends java.awt.RenderingHints.Key { + + public Key(int privateKey) { + super(privateKey); + } + + @Override + public boolean isCompatibleValue(Object val) { + switch (intKey()) { + case 0: + return val == null || val instanceof String + || val instanceof Map; + case 1: + return val == null || val instanceof Object; + case 2: + return val == null || val instanceof Object; + default: + throw new RuntimeException("Not possible!"); + } + } + } + /** * A rendering hint for storing the boundaries of the control area within a * Graphics2D instance. diff --git a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/IG2DNode.java b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/IG2DNode.java index 0afebc2db..e181d59ff 100644 --- a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/IG2DNode.java +++ b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/IG2DNode.java @@ -71,6 +71,14 @@ public interface IG2DNode extends INode, IEventHandler { */ public void render(Graphics2D g2d); + /** + * Visit the IG2DNode substructure of this node using the provided visitor. + * + * @param visitor the visitor to use + * @since 1.29.0 + */ + public void accept(IG2DNodeVisitor visitor); + /** * Mark the scene graph to be repainted in its current rendering context (UI * component) as soon as is appropriate for the backend system. diff --git a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/IG2DNodeVisitor.java b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/IG2DNodeVisitor.java new file mode 100644 index 000000000..2f5211714 --- /dev/null +++ b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/IG2DNodeVisitor.java @@ -0,0 +1,23 @@ +/******************************************************************************* + * Copyright (c) 2017 Association for Decentralized Information Management + * in Industry THTH ry. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Semantum Oy - initial API and implementation + *******************************************************************************/ +package org.simantics.scenegraph.g2d; + +/** + * @author Antti Villberg + * @since 1.29.0 + */ +public interface IG2DNodeVisitor { + + public void enter(IG2DNode node); + public void leave(IG2DNode node); + +} diff --git a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/ConnectionNode.java b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/ConnectionNode.java index a83ca5264..d4543c6d1 100644 --- a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/ConnectionNode.java +++ b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/ConnectionNode.java @@ -13,11 +13,13 @@ package org.simantics.scenegraph.g2d.nodes; import java.awt.Color; import java.awt.Composite; +import java.awt.Graphics2D; import java.awt.Stroke; import java.awt.geom.Point2D; import org.simantics.diagram.connection.RouteGraph; import org.simantics.scenegraph.INode; +import org.simantics.scenegraph.g2d.G2DRenderingHints; import org.simantics.scenegraph.g2d.IG2DNode; import org.simantics.scenegraph.g2d.events.MouseEvent; import org.simantics.scenegraph.g2d.nodes.connection.RouteGraphNode; @@ -150,4 +152,14 @@ public class ConnectionNode extends SingleElementNode implements InitValueSuppor return false; } + @Override + public void beforeRender(Graphics2D g) { + g.setRenderingHint(G2DRenderingHints.KEY_BEGIN_ELEMENT, "connection"); + } + + @Override + public void afterRender(Graphics2D g) { + g.setRenderingHint(G2DRenderingHints.KEY_END_ELEMENT, "connection"); + } + } diff --git a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/SVGNode.java b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/SVGNode.java index d50c65056..cdd6a2645 100644 --- a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/SVGNode.java +++ b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/SVGNode.java @@ -478,4 +478,11 @@ public class SVGNode extends G2DNode implements InitValueSupport, LoaderNode { this.setTransform(new AffineTransform(data)); } + public String getSVGText() { + String ret = data.replace("", "g>"); + //return diagramCache.toString(); + //return data.replace("", "/g>"); + return ret; + } + } diff --git a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/SingleElementNode.java b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/SingleElementNode.java index 00ca6b866..beee2538a 100644 --- a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/SingleElementNode.java +++ b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/SingleElementNode.java @@ -17,6 +17,7 @@ import java.awt.Graphics2D; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; +import org.simantics.scenegraph.g2d.G2DRenderingHints; import org.simantics.scenegraph.g2d.IG2DNode; import org.simantics.scenegraph.g2d.events.EventTypes; import org.simantics.scenegraph.g2d.events.MouseEvent; @@ -32,6 +33,15 @@ public class SingleElementNode extends TransformNode implements InitValueSupport protected Composite composite; protected Boolean visible = Boolean.TRUE; protected Boolean hidden = Boolean.FALSE; + private transient Object key; + + public void setKey(Object key) { + this.key = key; + } + + public Object getKey() { + return key; + } public void setTransferableProvider(TransferableProvider transferableProvider) { if (transferableProvider != this.transferableProvider) { @@ -169,4 +179,12 @@ public class SingleElementNode extends TransformNode implements InitValueSupport return EventTypes.MouseDragBeginMask; } + public void beforeRender(Graphics2D g) { + g.setRenderingHint(G2DRenderingHints.KEY_BEGIN_ELEMENT, "definedElement"); + } + + public void afterRender(Graphics2D g) { + g.setRenderingHint(G2DRenderingHints.KEY_END_ELEMENT, "definedElement"); + } + } diff --git a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/UnboundedNode.java b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/UnboundedNode.java index 4cacc70f9..b5071941f 100644 --- a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/UnboundedNode.java +++ b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/UnboundedNode.java @@ -11,6 +11,7 @@ *******************************************************************************/ package org.simantics.scenegraph.g2d.nodes; +import java.awt.Graphics2D; import java.awt.geom.Rectangle2D; public class UnboundedNode extends SingleElementNode { @@ -22,4 +23,12 @@ public class UnboundedNode extends SingleElementNode { return null; } + @Override + public void beforeRender(Graphics2D g) { + } + + @Override + public void afterRender(Graphics2D g) { + } + } -- 2.43.2