package org.simantics.modeling; import java.awt.Dimension; import java.awt.RenderingHints.Key; import java.awt.geom.Rectangle2D; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.UnsupportedEncodingException; import java.io.Writer; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Set; import java.util.UUID; import org.apache.batik.dom.GenericDOMImplementation; import org.apache.batik.svggen.SVGGraphics2D; 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.G2DHints; 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.g2d.nodes.spatial.RTreeNode; import org.simantics.scenegraph.utils.NodeUtil; import org.simantics.trend.impl.ItemNode; import org.simantics.utils.threads.ThreadUtils; import org.w3c.dom.DOMImplementation; import org.w3c.dom.Document; import org.w3c.dom.Element; 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; } 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(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(G2DHints.KEY_BEGIN_ELEMENT == arg0) { elemLevel++; } if(G2DHints.KEY_ELEMENT_ID == arg0) { if(arg1 != null) newElementId = arg1.toString(); else newElementId = UUID.randomUUID().toString(); } if(G2DHints.KEY_END_ELEMENT == arg0) { elemLevel--; if(elemLevel == 0) { 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 String renderSVG(ICanvasContext ctx) { // 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); try { 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); // 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; svgGenerator.scale(scale, scale); // Set svgCanvasSize to the given size parameters svgGenerator.setSVGCanvasSize(new Dimension((int)(scale * content.getWidth()), (int)(scale * content.getHeight()))); svgGenerator.setClip(content); sg.render(svgGenerator); } finally { } String result = ""; // Finally, stream out SVG to the standard output using // UTF-8 encoding. boolean useCSS = true; // we want to use CSS style attributes try { ByteArrayOutputStream os = new ByteArrayOutputStream(); Writer out = new OutputStreamWriter(os, "UTF-8"); svgGenerator.stream(out, useCSS); os.flush(); os.close(); result = new String(os.toByteArray());//Base64.encode(os.toByteArray()); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return result; } }