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=6345a132985c875bdf5b02cf5b2bc73e6d06f9a3;hp=b807136ef4b483d88e97381a005eb6b56f55ebb2;hb=76061fee3ffb1b66ed4d78ce711ab44f38b7ffdf;hpb=969bd23cab98a79ca9101af33334000879fb60c5 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 b807136ef..6345a1329 100644 --- a/bundles/org.simantics.modeling/src/org/simantics/modeling/SCLScenegraph.java +++ b/bundles/org.simantics.modeling/src/org/simantics/modeling/SCLScenegraph.java @@ -1,290 +1,821 @@ -package org.simantics.modeling; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Set; - -import org.simantics.db.Resource; -import org.simantics.db.exception.DatabaseException; -import org.simantics.diagram.elements.DiagramNodeUtil; -import org.simantics.diagram.elements.TextGridNode; -import org.simantics.diagram.elements.TextNode; -import org.simantics.g2d.canvas.ICanvasContext; -import org.simantics.g2d.diagram.DiagramHints; -import org.simantics.g2d.diagram.IDiagram; -import org.simantics.g2d.diagram.handler.DataElementMap; -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.ParentNode; -import org.simantics.scenegraph.g2d.G2DParentNode; -import org.simantics.scenegraph.g2d.G2DSceneGraph; -import org.simantics.scenegraph.g2d.events.command.Commands; -import org.simantics.scenegraph.g2d.nodes.BackgroundNode; -import org.simantics.scenegraph.g2d.nodes.BoundsNode; -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.SingleElementNode; -import org.simantics.scenegraph.utils.NodeUtil; -import org.simantics.trend.impl.ItemNode; -import org.simantics.utils.threads.ThreadUtils; - -public class SCLScenegraph { - - public static ICanvasSceneGraphProvider getICanvasSceneGraphProvider(Resource model, Resource diagram, String diagramRVI) throws DatabaseException, InterruptedException { - ICanvasSceneGraphProvider provider = DiagramNodeUtil.loadSceneGraphProvider(model, diagram, diagramRVI); - return provider; - } - - public static void disposeSceneGraphProvider(ICanvasSceneGraphProvider provider) { - 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); - for (TextNode text : texts) { - String nodeName = NodeUtil.getNodeName(text); - if (nodeName.equals(name)) { - String transform = text.getTransform().toString(); - return transform; - } - } - return "No node found"; - } - - public static String getNodeText(ICanvasContext ctx, String name) { - - Set texts = NodeUtil.collectNodes(ctx.getSceneGraph(), TextNode.class); - for (TextNode text : texts) { - String nodeName = NodeUtil.getNodeName(text); - if (nodeName.equals(name)) { - String texti = text.getText(); - return texti; - } - } - return "No node found"; - } - - public static String getNodeCount(ICanvasContext ctx) { - G2DSceneGraph g2 = ctx.getSceneGraph(); - int amount = NodeUtil.countTreeNodes(g2); - return "Node count: " + amount; - } - - public static String getAllNodes (ICanvasContext ctx) { - - Set g2 = NodeUtil.collectNodes(ctx.getSceneGraph(), G2DSceneGraph.class); - int amount = g2.size() +1; - return "All nodes: " + amount; - } - - public static String getBoundsNodes (ICanvasContext ctx) { - - Set bn = NodeUtil.collectNodes(ctx.getSceneGraph(), BoundsNode.class); - int amount = bn.size(); - return "BoundsNodes: " + amount; - } - - public static String getBackgroundNodes (ICanvasContext ctx) { - - Set bg = NodeUtil.collectNodes(ctx.getSceneGraph(), BackgroundNode.class); - int amount = bg.size(); - return "BackgroundNodes: " + amount; - } - - public static String getDataNodes (ICanvasContext ctx) { - - Set dn = NodeUtil.collectNodes(ctx.getSceneGraph(), DataNode.class); - int amount = dn.size(); - return "DataNodes: " + amount; - } - - public static String getNavigationNodes (ICanvasContext ctx) { - - Set g2 = NodeUtil.collectNodes(ctx.getSceneGraph(), NavigationNode.class); - int amount = g2.size(); - return "NavigationNodes: " + amount; - } - - public static String getParentNodes (ICanvasContext ctx) { - - Set g2 = NodeUtil.collectNodes(ctx.getSceneGraph(), G2DParentNode.class); - int amount = g2.size(); - return "ParentNodes: " + amount; - } - - public static String getDecorationNodes (ICanvasContext ctx) { - - Set deco = NodeUtil.collectNodes(ctx.getSceneGraph(), DecorationSVGNode.class); - int amount = deco.size(); - return "DecorationNodes: " + amount; - } - - public static String getSingleElementNodes (ICanvasContext ctx) { - - Set g2 = NodeUtil.collectNodes(ctx.getSceneGraph(), SingleElementNode.class); - int amount = g2.size(); - return "SingleElementNodes: " + amount; - } - - public static String getConnectionNodes (ICanvasContext ctx) { - - Set g2 = NodeUtil.collectNodes(ctx.getSceneGraph(), ConnectionNode.class); - int amount = g2.size(); - return "ConnectionNodes: " + amount; - } - - public static String getTextNodes (ICanvasContext ctx) { - - Set tn = NodeUtil.collectNodes(ctx.getSceneGraph(), TextNode.class); - Set tgn = NodeUtil.collectNodes(ctx.getSceneGraph(), TextGridNode.class); - int amount = tn.size() + tgn.size(); - return "TextNodes: " + amount; - } - - public static String getItemNodes (ICanvasContext ctx) { - - Set item = NodeUtil.collectNodes(ctx.getSceneGraph(), ItemNode.class); - int amount = item.size(); - return "ItemNodes: " + amount; - } - - public static String editNodeText (ICanvasContext ctx, String module, String previous_value, String new_value) { - - Set textGridNodes = NodeUtil.collectNodes(ctx.getSceneGraph(), TextNode.class); - for (TextNode modulenode : textGridNodes) { - if (module.equals(modulenode.getText())) { - //System.out.println("Module what we were looking for: " + module); - //System.out.println("Modulenode: " + modulenode.getText()); - - ParentNode parentnode = modulenode.getParent(); - //System.out.println("Parentnode: " + parentnode); - - Collection textnodes = (Collection) parentnode.getNodes(); - for (TextNode valuenode : textnodes) { - if (previous_value.equals(valuenode.getText())) { - //System.out.println("Value what we were looking for: " + previous_value); - //System.out.println("Valuenode: " + valuenode.getText()); - - //valuenode.setEditMode(true); - valuenode.activateEdit(0, null, ctx); - valuenode.setText(new_value); - valuenode.fireTextEditingEnded(); - - //System.out.println("valuenode modified: " + valuenode); - return "Modified module " + module + " with value " + new_value; - } - } - return "Not found module : " + module; - } - } - return "No nodes in scenegraph!"; - } - - public static String sceneGraphTest (ICanvasContext ctx, String module, String value) { - - boolean module_founded = false; - boolean value_founded = false; - - Set g2 = NodeUtil.collectNodes(ctx.getSceneGraph(), G2DSceneGraph.class); - System.out.println("Total amount of nodes: " + g2.size() + 1); - - Set grid = NodeUtil.collectNodes(ctx.getSceneGraph(), TextGridNode.class); - Integer textGridNodeAmount = grid.size(); - System.out.println("Amount of TextGridNodes " + textGridNodeAmount); - - Set texts = NodeUtil.collectNodes(ctx.getSceneGraph(), TextNode.class); - Integer textNodeAmount = grid.size(); - System.out.println("Amount of TextNodes " + textNodeAmount); - - for (TextNode node : texts) { - if (module.equals(node.getText())) { - module_founded = true; - System.out.println("Correct module " + module + " founded."); - } - if (value.equals(node.getText())) { - value_founded = true; - System.out.println("Correct value " + value + " founded."); - } - } - - if (value_founded == true && module_founded == true) { - return "Found both correct module " + module + " and value " + value; - } - if (value_founded == false && module_founded == true) { - return "Found only correct module " + module + " but not value " + value; - } - if (value_founded == true && module_founded == false) { - return "Found only correct value " + value + " but not module " + module; - } - else { - return "Didn't found either module " + module + " or value " + value; - } - } - - 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); - - DataElementMap dem = idiagram.getDiagramClass().getAtMostOneItemOfClass(DataElementMap.class); - if (dem != null) { - final Collection newSelection = new ArrayList(); - for (Resource module : modules) { - IElement element = dem.getElement(idiagram, module); - if (element != null) { - newSelection.add(element); - } else { - throw new DatabaseException("Could not find IElement for " + element); - } - } - - ThreadUtils.syncExec(source_ctx.getThreadAccess(), new Runnable() { - @Override - public void run() { - if (source_ctx.isDisposed()) - return; - Selection selection = source_ctx.getAtMostOneItemOfClass(Selection.class); - if (selection != null) { - // This prevents workbench selection from being left over. - // Also prevents scene graph crap from being left on the screen. - selection.setSelection(0, newSelection); - } - CanvasUtils.sendCommand(source_ctx, Commands.COPY); - CanvasUtils.sendCommand(target_ctx, Commands.PASTE); - } - }); - - //} - - while(source_ctx.getEventQueue().size() > 0) { - try { - Thread.sleep(10); - } catch (InterruptedException e) { - throw new DatabaseException(e); - } - } - - ThreadUtils.syncExec(source_ctx.getThreadAccess(), new Runnable() { - @Override - public void run() { - } - }); - - } - return true; - } - - +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.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.Set; +import java.util.UUID; +import java.util.stream.Collectors; + +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.Simantics; +import org.simantics.datatypes.literal.GUID; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.common.request.UnaryRead; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.exception.RuntimeDatabaseException; +import org.simantics.diagram.elements.DiagramNodeUtil; +import org.simantics.diagram.elements.TextGridNode; +import org.simantics.diagram.elements.TextNode; +import org.simantics.diagram.stubs.DiagramResource; +import org.simantics.g2d.canvas.ICanvasContext; +import org.simantics.g2d.diagram.DiagramHints; +import org.simantics.g2d.diagram.IDiagram; +import org.simantics.g2d.diagram.handler.DataElementMap; +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.layer0.Layer0; +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; +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.scl.runtime.function.Function1; +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; + } + + public static void disposeSceneGraphProvider(ICanvasSceneGraphProvider provider) { + provider.dispose(); + } + + public static String getNodeTransform(ICanvasContext ctx, String name) { + + Set texts = NodeUtil.collectNodes(ctx.getSceneGraph(), TextNode.class); + for (TextNode text : texts) { + String nodeName = NodeUtil.getNodeName(text); + if (nodeName.equals(name)) { + String transform = text.getTransform().toString(); + return transform; + } + } + return "No node found"; + } + + public static String getNodeText(ICanvasContext ctx, String name) { + + Set texts = NodeUtil.collectNodes(ctx.getSceneGraph(), TextNode.class); + for (TextNode text : texts) { + String nodeName = NodeUtil.getNodeName(text); + if (nodeName.equals(name)) { + String texti = text.getText(); + return texti; + } + } + return "No node found"; + } + + public static String getNodeCount(ICanvasContext ctx) { + G2DSceneGraph g2 = ctx.getSceneGraph(); + int amount = NodeUtil.countTreeNodes(g2); + return "Node count: " + amount; + } + + public static String getAllNodes (ICanvasContext ctx) { + + Set g2 = NodeUtil.collectNodes(ctx.getSceneGraph(), G2DSceneGraph.class); + int amount = g2.size() +1; + return "All nodes: " + amount; + } + + public static String getBoundsNodes (ICanvasContext ctx) { + + Set bn = NodeUtil.collectNodes(ctx.getSceneGraph(), BoundsNode.class); + int amount = bn.size(); + return "BoundsNodes: " + amount; + } + + public static String getBackgroundNodes (ICanvasContext ctx) { + + Set bg = NodeUtil.collectNodes(ctx.getSceneGraph(), BackgroundNode.class); + int amount = bg.size(); + return "BackgroundNodes: " + amount; + } + + public static String getDataNodes (ICanvasContext ctx) { + + Set dn = NodeUtil.collectNodes(ctx.getSceneGraph(), DataNode.class); + int amount = dn.size(); + return "DataNodes: " + amount; + } + + public static String getNavigationNodes (ICanvasContext ctx) { + + Set g2 = NodeUtil.collectNodes(ctx.getSceneGraph(), NavigationNode.class); + int amount = g2.size(); + return "NavigationNodes: " + amount; + } + + public static String getParentNodes (ICanvasContext ctx) { + + Set g2 = NodeUtil.collectNodes(ctx.getSceneGraph(), G2DParentNode.class); + int amount = g2.size(); + return "ParentNodes: " + amount; + } + + public static String getDecorationNodes (ICanvasContext ctx) { + + Set deco = NodeUtil.collectNodes(ctx.getSceneGraph(), DecorationSVGNode.class); + int amount = deco.size(); + return "DecorationNodes: " + amount; + } + + public static String getSingleElementNodes (ICanvasContext ctx) { + + Set g2 = NodeUtil.collectNodes(ctx.getSceneGraph(), SingleElementNode.class); + int amount = g2.size(); + return "SingleElementNodes: " + amount; + } + + public static String getConnectionNodes (ICanvasContext ctx) { + + Set g2 = NodeUtil.collectNodes(ctx.getSceneGraph(), ConnectionNode.class); + int amount = g2.size(); + return "ConnectionNodes: " + amount; + } + + public static String getTextNodes (ICanvasContext ctx) { + + Set tn = NodeUtil.collectNodes(ctx.getSceneGraph(), TextNode.class); + Set tgn = NodeUtil.collectNodes(ctx.getSceneGraph(), TextGridNode.class); + int amount = tn.size() + tgn.size(); + return "TextNodes: " + amount; + } + + public static String getItemNodes (ICanvasContext ctx) { + + Set item = NodeUtil.collectNodes(ctx.getSceneGraph(), ItemNode.class); + int amount = item.size(); + return "ItemNodes: " + amount; + } + + public static String editNodeText (ICanvasContext ctx, String module, String previous_value, String new_value) { + + Set textGridNodes = NodeUtil.collectNodes(ctx.getSceneGraph(), TextNode.class); + for (TextNode modulenode : textGridNodes) { + if (module.equals(modulenode.getText())) { + //System.out.println("Module what we were looking for: " + module); + //System.out.println("Modulenode: " + modulenode.getText()); + + ParentNode parentnode = modulenode.getParent(); + //System.out.println("Parentnode: " + parentnode); + + Collection textnodes = (Collection) parentnode.getNodes(); + for (TextNode valuenode : textnodes) { + if (previous_value.equals(valuenode.getText())) { + //System.out.println("Value what we were looking for: " + previous_value); + //System.out.println("Valuenode: " + valuenode.getText()); + + //valuenode.setEditMode(true); + valuenode.activateEdit(0, null, ctx); + valuenode.setText(new_value); + valuenode.fireTextEditingEnded(); + + //System.out.println("valuenode modified: " + valuenode); + return "Modified module " + module + " with value " + new_value; + } + } + return "Not found module : " + module; + } + } + return "No nodes in scenegraph!"; + } + + public static String sceneGraphTest (ICanvasContext ctx, String module, String value) { + + boolean module_founded = false; + boolean value_founded = false; + + Set g2 = NodeUtil.collectNodes(ctx.getSceneGraph(), G2DSceneGraph.class); + System.out.println("Total amount of nodes: " + g2.size() + 1); + + Set grid = NodeUtil.collectNodes(ctx.getSceneGraph(), TextGridNode.class); + Integer textGridNodeAmount = grid.size(); + System.out.println("Amount of TextGridNodes " + textGridNodeAmount); + + Set texts = NodeUtil.collectNodes(ctx.getSceneGraph(), TextNode.class); + Integer textNodeAmount = grid.size(); + System.out.println("Amount of TextNodes " + textNodeAmount); + + for (TextNode node : texts) { + if (module.equals(node.getText())) { + module_founded = true; + System.out.println("Correct module " + module + " founded."); + } + if (value.equals(node.getText())) { + value_founded = true; + System.out.println("Correct value " + value + " founded."); + } + } + + if (value_founded == true && module_founded == true) { + return "Found both correct module " + module + " and value " + value; + } + if (value_founded == false && module_founded == true) { + return "Found only correct module " + module + " but not value " + value; + } + if (value_founded == true && module_founded == false) { + return "Found only correct value " + value + " but not module " + module; + } + else { + return "Didn't found either module " + module + " or value " + value; + } + } + + 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); + + DataElementMap dem = idiagram.getDiagramClass().getAtMostOneItemOfClass(DataElementMap.class); + if (dem != null) { + final Collection newSelection = new ArrayList(); + for (Resource module : modules) { + IElement element = dem.getElement(idiagram, module); + if (element != null) { + newSelection.add(element); + } else { + throw new DatabaseException("Could not find IElement for " + element); + } + } + + ThreadUtils.syncExec(source_ctx.getThreadAccess(), new Runnable() { + @Override + public void run() { + if (source_ctx.isDisposed()) + return; + Selection selection = source_ctx.getAtMostOneItemOfClass(Selection.class); + if (selection != null) { + // This prevents workbench selection from being left over. + // Also prevents scene graph crap from being left on the screen. + selection.setSelection(0, newSelection); + } + CanvasUtils.sendCommand(source_ctx, Commands.COPY); + CanvasUtils.sendCommand(target_ctx, Commands.PASTE); + } + }); + + //} + + while(source_ctx.getEventQueue().size() > 0) { + try { + Thread.sleep(10); + } catch (InterruptedException e) { + throw new DatabaseException(e); + } + } + + ThreadUtils.syncExec(source_ctx.getThreadAccess(), new Runnable() { + @Override + public void run() { + } + }); + + } + 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 p0.stream().collect(Collectors.toMap(p1 -> p1, p2 -> p2))); + } + + /** + * @param graph + * @param component + * @throws DatabaseException + */ + private static Object[] createURIBasedL0Identifier(ReadGraph graph, Resource component) throws DatabaseException { + String uri = graph.getPossibleURI(component); + int hashCode = uri.hashCode(); + Random random = new Random(hashCode); + long l1 = random.nextLong(); + long l2 = random.nextLong(); + return new Object[] { l1, l2 }; + } + + /** + * Default no-op mapper + */ + private static final Function1, Map> mapper = p0 -> p0.stream().collect(Collectors.toMap(p1 -> p1, p2 -> p2)); + + public static String renderSVG(ICanvasContext ctx) { + return renderSVG0(ctx, mapper); + } + + /** + * Renders ICanvasContext into SVG by mapping the SVG id's into URI based + * GUID's + * + * @param ctx + * @return + */ + public static String renderSVGMapIdentifiers(ICanvasContext ctx) { + return renderSVG0(ctx, new Function1, Map>() { + + @Override + public Map apply(Set p0) { + try { + return Simantics.getSession().syncRequest(new UnaryRead, Map>(p0) { + + @Override + public Map perform(ReadGraph graph) throws DatabaseException { + ModelingResources MOD = ModelingResources.getInstance(graph); + DiagramResource DIA = DiagramResource.getInstance(graph); + Layer0 L0 = Layer0.getInstance(graph); + return parameter.stream().collect(Collectors.toMap(p -> p, p -> { + try { + if (p instanceof Resource) { + Resource element = (Resource) p; + if (graph.isInstanceOf(element, DIA.Element)) { + Resource component = graph.getPossibleObject(element, MOD.ElementToComponent); + if (component != null) { + GUID identifier = graph.getPossibleRelatedValue(component, L0.identifier, GUID.BINDING); + if (identifier != null) { + return Arrays.toString(createURIBasedL0Identifier(graph, component)); + } else { + LOGGER.error("Component {} does not have GUID identifier!", component); + } + } else if (graph.isInstanceOf(element, DIA.Connection) || graph.isInstanceOf(element, DIA.Terminal)) { + // Ok, lets create a hashcode for connections and terminals as they do not have identifiers + return graph.getURI(element).hashCode(); + } else { + // Ok, lets create a hashcode or either return empty string in cases where no ID is required + if (graph.hasStatement(element, L0.HasName)) + return graph.getURI(element).hashCode(); + return ""; + } + } + } else { + LOGGER.error("Parameter p {} is not resource but it is {}", p, p.getClass()); + } + return p; + } catch (DatabaseException e) { + throw new RuntimeDatabaseException(e); + } + })); + } + }); + } catch (DatabaseException e) { + LOGGER.error("Could not apply mappings", e); + throw new RuntimeDatabaseException(e); + } + } + }); + } + + private static String renderSVG0(ICanvasContext ctx, Function1, Map> mappingFunction) { + + // 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); + + // Create an instance of the SVG Generator. + SVGGraphics2D svgGenerator = new Generator(document); + + StringBuilder result = new StringBuilder(); + + try { + + Selection selection = ctx.getAtMostOneItemOfClass(Selection.class); + if (selection != null) { + // This prevents workbench selection from being left over. + // Also prevents scene graph crap from being left on the screen. + IDiagram d = ctx.getDefaultHintContext().getHint(DiagramHints.KEY_DIAGRAM); + selection.setSelection(0, d.getElements()); + } + + G2DSceneGraph sg = ctx.getSceneGraph(); + G2DParentNode root = (G2DParentNode) sg.getRootNode(); + + // rtree is the actual content of the diagram + RTreeNode rtree = NodeUtil.getNearestChildByClass(root, RTreeNode.class); + Rectangle2D rtreeBounds = NodeUtil.getLocalBounds(rtree); + + // nav is a node that has zooming functionalities + NavigationNode nav = NodeUtil.getNearestChildByClass(root, NavigationNode.class); + nav.setZoomEnabled(true); + + // fit view with the contents of rtreeBounds + nav.zoomTo(rtreeBounds); + + // get the bounds of the content + Rectangle2D content = NodeUtil.getLocalBounds(nav); + + svgGenerator.scale(3,3); + + // translate svgGenerator to the x and y coordinates of current content + svgGenerator.translate(-1 * content.getX(), (-1 * content.getY())); + + Rectangle2D destination = new Rectangle2D.Double(0,0,1000,1000); + double sx = destination.getWidth() / content.getWidth(); + double sy = destination.getHeight() / content.getHeight(); + double scale = sx < sy ? sx : sy; + + // Set svgCanvasSize to the given size parameters + svgGenerator.setSVGCanvasSize(new Dimension((int)(scale * content.getWidth()), (int)(scale * content.getHeight()))); + svgGenerator.setClip(content); + + double trX = -1 * content.getX(); + double trY = -1 * content.getY(); + + result.append(""); + + KeyVisitor keyVisitor = new KeyVisitor(); + sg.accept(keyVisitor); + + Set keys = keyVisitor.getKeys(); + + Map mappings = mappingFunction.apply(keys); + + IG2DNodeVisitor visitor = new PrintingVisitor(result, mappings); + 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(); + } + + + + private static class KeyVisitor implements IG2DNodeVisitor { + + private Set keys = new HashSet<>(); + + @Override + public void enter(IG2DNode node) { + if (node instanceof SingleElementNode) { + Object key = ((SingleElementNode) node).getKey(); + if (key != null) { + keys.add(key); + } + } + } + + @Override + public void leave(IG2DNode node) { + // Nothing to do + } + + public Set getKeys() { + return keys; + } + } + + private static class PrintingVisitor implements IG2DNodeVisitor { + + int indent = 0; + + HashMap senBuilders = new HashMap<>(); + + private StringBuilder result; + + private Map mappings; + + public PrintingVisitor(StringBuilder result, Map mappings) { + this.result = result; + this.mappings = mappings; + } + + private String getKey(SingleElementNode node) { + String key; + if (mappings.containsKey(node.getKey())) + key = mappings.get(node.getKey()).toString(); + else + key = node.getKey().toString(); + return key; + } + + @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 = getKey((ConnectionNode) node); + 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 = getKey(parentSEN); + 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 = getKey(sen); + 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 --; + } + } } \ No newline at end of file