X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.modeling%2Fsrc%2Forg%2Fsimantics%2Fmodeling%2FSCLScenegraph.java;h=5dde0b081677a9e41dac64ff7ea8c7934d789408;hp=33d7f06290e109e69fdc4ceff7afb00c8b7cd00a;hb=3a10ce856f7124f83cf03d6e7f7576da237a7cbb;hpb=0ae2b770234dfc3cbb18bd38f324125cf0faca07 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..5dde0b081 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,29 @@ package org.simantics.modeling; +import java.awt.BasicStroke; +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; @@ -18,9 +37,13 @@ import org.simantics.g2d.diagram.participant.Selection; import org.simantics.g2d.element.IElement; import org.simantics.g2d.scenegraph.ICanvasSceneGraphProvider; import org.simantics.g2d.utils.CanvasUtils; +import org.simantics.scenegraph.INode; 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 +51,25 @@ 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.SelectionNode; import org.simantics.scenegraph.g2d.nodes.SingleElementNode; +import org.simantics.scenegraph.g2d.nodes.connection.RouteGraphNode; +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 +79,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 +262,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 +314,359 @@ 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 senBuilders = new HashMap<>(); + + @Override + public void enter(IG2DNode node) { + + StringBuilder parentBuilder = getParentBuilder(node); + + indent++; + if(node instanceof ConnectionNode) { + + for(RouteGraphNode n : NodeUtil.collectNodes(node, RouteGraphNode.class)) { + n.setIgnoreSelection(true); + } + + String key = ((ConnectionNode)node).getKey().toString(); + + parentBuilder.append("\n"); + Element doc = renderSVGNode((IG2DNode)node); + String svg = printSVGDocument(doc); + parentBuilder.append(svg); + + for(RouteGraphNode n : NodeUtil.collectNodes(node, RouteGraphNode.class)) { + n.setIgnoreSelection(false); + } + + parentBuilder.append("\n"); + doc = renderSVGNode((IG2DNode)node); + svg = printSVGDocument(doc); + parentBuilder.append(svg); + parentBuilder.append("\n"); + + BasicStroke bs = new BasicStroke(5f); + + for(RouteGraphNode n : NodeUtil.collectNodes(node, RouteGraphNode.class)) { + n.setDynamicStroke(bs); + } + + parentBuilder.append("\n"); + doc = renderSVGNode((IG2DNode)node); + svg = printSVGDocument(doc); + parentBuilder.append(svg); + parentBuilder.append("\n"); + + parentBuilder.append("\n"); + + } else if (node instanceof SelectionNode) { + + SelectionNode n = (SelectionNode)node; + SingleElementNode parentSEN = (SingleElementNode)NodeUtil.getNearestParentOfType(node, SingleElementNode.class); + if(parentSEN != null && parentSEN.getKey() != null) { + + StringBuilder parentBuilder2 = getParentBuilder(parentSEN); + + String key = parentSEN.getKey().toString(); + Element doc = renderSVGNode((IG2DNode)node); + String svg = printSVGDocument(doc); + parentBuilder2.append("\n"); + parentBuilder2.append(svg); + parentBuilder2.append("\n"); + parentBuilder2.append("\n"); + Rectangle2D rect = n.getRect(); + parentBuilder2.append(""); + parentBuilder2.append("\n"); + } + } else if (node instanceof SVGNode) { + SVGNode svg = (SVGNode)node; + parentBuilder.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(); + parentBuilder.append("\n"); + } + senBuilders.put(sen, new StringBuilder()); + } + 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() + ")"; + parentBuilder.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] + ")"; + parentBuilder.append("\n"); + } + } + } + + //enters.put(node, b.length()); + + } + + private StringBuilder getParentBuilder(IG2DNode node) { + + INode parentSEN = NodeUtil.getNearestParentOfType(node, SingleElementNode.class); + if(parentSEN instanceof G2DSceneGraph) return result; + + StringBuilder parentBuilder = senBuilders.get(parentSEN); + if(parentBuilder == null) return result; + + return parentBuilder; + + } + + @Override + public void leave(IG2DNode node) { + + if(node instanceof ConnectionNode || node instanceof SVGNode) { + // We are done + } else if (node instanceof G2DParentNode) { + + StringBuilder parentBuilder = getParentBuilder(node); + + if(node instanceof SingleElementNode) { + SingleElementNode sen = (SingleElementNode)node; +// if(sen.getKey() != null) { + StringBuilder b = senBuilders.get(sen); + String content = b.toString(); + if(content.isEmpty()) { + if(sen.getKey() != null) { + + for(SelectionNode n : NodeUtil.collectNodes(node, SelectionNode.class)) { + n.setIgnore(true); + } + + Element doc = renderSVGNode((IG2DNode)node); + String svg = printSVGDocument(doc); + parentBuilder.append(svg); + } + } else { + parentBuilder.append(content); + } +// } + } + + + AffineTransform at = node.getTransform(); + if(!at.isIdentity()) { + parentBuilder.append(""); + } + if(node instanceof SingleElementNode) { + SingleElementNode sen = (SingleElementNode)node; + if(sen.getKey() != null) { + parentBuilder.append(""); + } + } + } + indent --; + } + + }; + sg.accept(visitor); + + } catch (Throwable t) { + LOGGER.error("Problems rendering canvas context to SVG", t); + } + + result.append(""); + //System.err.println(" == FINAL RESULT == "); + //System.err.println(b); + return result.toString(); + + } + } \ No newline at end of file