1 package org.simantics.modeling;
3 import java.awt.Dimension;
4 import java.awt.RenderingHints.Key;
5 import java.awt.geom.Rectangle2D;
6 import java.io.ByteArrayOutputStream;
7 import java.io.IOException;
8 import java.io.OutputStreamWriter;
9 import java.io.UnsupportedEncodingException;
10 import java.io.Writer;
11 import java.util.ArrayList;
12 import java.util.Collection;
13 import java.util.List;
15 import java.util.UUID;
17 import org.apache.batik.dom.GenericDOMImplementation;
18 import org.apache.batik.svggen.SVGGraphics2D;
19 import org.simantics.db.Resource;
20 import org.simantics.db.exception.DatabaseException;
21 import org.simantics.diagram.elements.DiagramNodeUtil;
22 import org.simantics.diagram.elements.TextGridNode;
23 import org.simantics.diagram.elements.TextNode;
24 import org.simantics.g2d.canvas.ICanvasContext;
25 import org.simantics.g2d.diagram.DiagramHints;
26 import org.simantics.g2d.diagram.IDiagram;
27 import org.simantics.g2d.diagram.handler.DataElementMap;
28 import org.simantics.g2d.diagram.participant.Selection;
29 import org.simantics.g2d.element.IElement;
30 import org.simantics.g2d.scenegraph.ICanvasSceneGraphProvider;
31 import org.simantics.g2d.utils.CanvasUtils;
32 import org.simantics.scenegraph.ParentNode;
33 import org.simantics.scenegraph.g2d.G2DHints;
34 import org.simantics.scenegraph.g2d.G2DParentNode;
35 import org.simantics.scenegraph.g2d.G2DSceneGraph;
36 import org.simantics.scenegraph.g2d.events.command.Commands;
37 import org.simantics.scenegraph.g2d.nodes.BackgroundNode;
38 import org.simantics.scenegraph.g2d.nodes.BoundsNode;
39 import org.simantics.scenegraph.g2d.nodes.ConnectionNode;
40 import org.simantics.scenegraph.g2d.nodes.DataNode;
41 import org.simantics.scenegraph.g2d.nodes.DecorationSVGNode;
42 import org.simantics.scenegraph.g2d.nodes.NavigationNode;
43 import org.simantics.scenegraph.g2d.nodes.SingleElementNode;
44 import org.simantics.scenegraph.g2d.nodes.spatial.RTreeNode;
45 import org.simantics.scenegraph.utils.NodeUtil;
46 import org.simantics.trend.impl.ItemNode;
47 import org.simantics.utils.threads.ThreadUtils;
48 import org.w3c.dom.DOMImplementation;
49 import org.w3c.dom.Document;
50 import org.w3c.dom.Element;
52 public class SCLScenegraph {
54 public static ICanvasSceneGraphProvider getICanvasSceneGraphProvider(Resource model, Resource diagram, String diagramRVI) throws DatabaseException, InterruptedException {
55 ICanvasSceneGraphProvider provider = DiagramNodeUtil.loadSceneGraphProvider(model, diagram, diagramRVI);
59 public static void disposeSceneGraphProvider(ICanvasSceneGraphProvider provider) {
63 //public static Resource getDiagramRuntime(Resource )
66 // public static String getNodeTransform(ICanvasContext ctx, String name) throws DatabaseException, InterruptedException {
67 // return getNodeTransform(ctx, name);
70 public static String getNodeTransform(ICanvasContext ctx, String name) {
72 Set<TextNode> texts = NodeUtil.collectNodes(ctx.getSceneGraph(), TextNode.class);
73 for (TextNode text : texts) {
74 String nodeName = NodeUtil.getNodeName(text);
75 if (nodeName.equals(name)) {
76 String transform = text.getTransform().toString();
80 return "No node found";
83 public static String getNodeText(ICanvasContext ctx, String name) {
85 Set<TextNode> texts = NodeUtil.collectNodes(ctx.getSceneGraph(), TextNode.class);
86 for (TextNode text : texts) {
87 String nodeName = NodeUtil.getNodeName(text);
88 if (nodeName.equals(name)) {
89 String texti = text.getText();
93 return "No node found";
96 public static String getNodeCount(ICanvasContext ctx) {
97 G2DSceneGraph g2 = ctx.getSceneGraph();
98 int amount = NodeUtil.countTreeNodes(g2);
99 return "Node count: " + amount;
102 public static String getAllNodes (ICanvasContext ctx) {
104 Set<G2DSceneGraph> g2 = NodeUtil.collectNodes(ctx.getSceneGraph(), G2DSceneGraph.class);
105 int amount = g2.size() +1;
106 return "All nodes: " + amount;
109 public static String getBoundsNodes (ICanvasContext ctx) {
111 Set<BoundsNode> bn = NodeUtil.collectNodes(ctx.getSceneGraph(), BoundsNode.class);
112 int amount = bn.size();
113 return "BoundsNodes: " + amount;
116 public static String getBackgroundNodes (ICanvasContext ctx) {
118 Set<BackgroundNode> bg = NodeUtil.collectNodes(ctx.getSceneGraph(), BackgroundNode.class);
119 int amount = bg.size();
120 return "BackgroundNodes: " + amount;
123 public static String getDataNodes (ICanvasContext ctx) {
125 Set<DataNode> dn = NodeUtil.collectNodes(ctx.getSceneGraph(), DataNode.class);
126 int amount = dn.size();
127 return "DataNodes: " + amount;
130 public static String getNavigationNodes (ICanvasContext ctx) {
132 Set<NavigationNode> g2 = NodeUtil.collectNodes(ctx.getSceneGraph(), NavigationNode.class);
133 int amount = g2.size();
134 return "NavigationNodes: " + amount;
137 public static String getParentNodes (ICanvasContext ctx) {
139 Set<G2DParentNode> g2 = NodeUtil.collectNodes(ctx.getSceneGraph(), G2DParentNode.class);
140 int amount = g2.size();
141 return "ParentNodes: " + amount;
144 public static String getDecorationNodes (ICanvasContext ctx) {
146 Set<DecorationSVGNode> deco = NodeUtil.collectNodes(ctx.getSceneGraph(), DecorationSVGNode.class);
147 int amount = deco.size();
148 return "DecorationNodes: " + amount;
151 public static String getSingleElementNodes (ICanvasContext ctx) {
153 Set<SingleElementNode> g2 = NodeUtil.collectNodes(ctx.getSceneGraph(), SingleElementNode.class);
154 int amount = g2.size();
155 return "SingleElementNodes: " + amount;
158 public static String getConnectionNodes (ICanvasContext ctx) {
160 Set<ConnectionNode> g2 = NodeUtil.collectNodes(ctx.getSceneGraph(), ConnectionNode.class);
161 int amount = g2.size();
162 return "ConnectionNodes: " + amount;
165 public static String getTextNodes (ICanvasContext ctx) {
167 Set<TextNode> tn = NodeUtil.collectNodes(ctx.getSceneGraph(), TextNode.class);
168 Set<TextGridNode> tgn = NodeUtil.collectNodes(ctx.getSceneGraph(), TextGridNode.class);
169 int amount = tn.size() + tgn.size();
170 return "TextNodes: " + amount;
173 public static String getItemNodes (ICanvasContext ctx) {
175 Set<ItemNode> item = NodeUtil.collectNodes(ctx.getSceneGraph(), ItemNode.class);
176 int amount = item.size();
177 return "ItemNodes: " + amount;
180 public static String editNodeText (ICanvasContext ctx, String module, String previous_value, String new_value) {
182 Set<TextNode> textGridNodes = NodeUtil.collectNodes(ctx.getSceneGraph(), TextNode.class);
183 for (TextNode modulenode : textGridNodes) {
184 if (module.equals(modulenode.getText())) {
185 //System.out.println("Module what we were looking for: " + module);
186 //System.out.println("Modulenode: " + modulenode.getText());
188 ParentNode<?> parentnode = modulenode.getParent();
189 //System.out.println("Parentnode: " + parentnode);
191 Collection<TextNode> textnodes = (Collection<TextNode>) parentnode.getNodes();
192 for (TextNode valuenode : textnodes) {
193 if (previous_value.equals(valuenode.getText())) {
194 //System.out.println("Value what we were looking for: " + previous_value);
195 //System.out.println("Valuenode: " + valuenode.getText());
197 //valuenode.setEditMode(true);
198 valuenode.activateEdit(0, null, ctx);
199 valuenode.setText(new_value);
200 valuenode.fireTextEditingEnded();
202 //System.out.println("valuenode modified: " + valuenode);
203 return "Modified module " + module + " with value " + new_value;
206 return "Not found module : " + module;
209 return "No nodes in scenegraph!";
212 public static String sceneGraphTest (ICanvasContext ctx, String module, String value) {
214 boolean module_founded = false;
215 boolean value_founded = false;
217 Set<G2DSceneGraph> g2 = NodeUtil.collectNodes(ctx.getSceneGraph(), G2DSceneGraph.class);
218 System.out.println("Total amount of nodes: " + g2.size() + 1);
220 Set<TextGridNode> grid = NodeUtil.collectNodes(ctx.getSceneGraph(), TextGridNode.class);
221 Integer textGridNodeAmount = grid.size();
222 System.out.println("Amount of TextGridNodes " + textGridNodeAmount);
224 Set<TextNode> texts = NodeUtil.collectNodes(ctx.getSceneGraph(), TextNode.class);
225 Integer textNodeAmount = grid.size();
226 System.out.println("Amount of TextNodes " + textNodeAmount);
228 for (TextNode node : texts) {
229 if (module.equals(node.getText())) {
230 module_founded = true;
231 System.out.println("Correct module " + module + " founded.");
233 if (value.equals(node.getText())) {
234 value_founded = true;
235 System.out.println("Correct value " + value + " founded.");
239 if (value_founded == true && module_founded == true) {
240 return "Found both correct module " + module + " and value " + value;
242 if (value_founded == false && module_founded == true) {
243 return "Found only correct module " + module + " but not value " + value;
245 if (value_founded == true && module_founded == false) {
246 return "Found only correct value " + value + " but not module " + module;
249 return "Didn't found either module " + module + " or value " + value;
253 public static boolean copyPaste (final ICanvasContext source_ctx, final ICanvasContext target_ctx, List<Resource> modules) throws DatabaseException {
255 IDiagram idiagram = source_ctx.getDefaultHintContext().getHint(DiagramHints.KEY_DIAGRAM);
257 DataElementMap dem = idiagram.getDiagramClass().getAtMostOneItemOfClass(DataElementMap.class);
259 final Collection<IElement> newSelection = new ArrayList<IElement>();
260 for (Resource module : modules) {
261 IElement element = dem.getElement(idiagram, module);
262 if (element != null) {
263 newSelection.add(element);
265 throw new DatabaseException("Could not find IElement for " + element);
269 ThreadUtils.syncExec(source_ctx.getThreadAccess(), new Runnable() {
272 if (source_ctx.isDisposed())
274 Selection selection = source_ctx.getAtMostOneItemOfClass(Selection.class);
275 if (selection != null) {
276 // This prevents workbench selection from being left over.
277 // Also prevents scene graph crap from being left on the screen.
278 selection.setSelection(0, newSelection);
280 CanvasUtils.sendCommand(source_ctx, Commands.COPY);
281 CanvasUtils.sendCommand(target_ctx, Commands.PASTE);
287 while(source_ctx.getEventQueue().size() > 0) {
290 } catch (InterruptedException e) {
291 throw new DatabaseException(e);
295 ThreadUtils.syncExec(source_ctx.getThreadAccess(), new Runnable() {
308 static class Generator extends SVGGraphics2D {
311 String newElementId = null;
312 ArrayList<Element> elements = new ArrayList<Element>();
314 public static final String svgNS = "http://www.w3.org/2000/svg";
316 public Generator(Document document) {
321 public Element getRoot() {
322 Element root = super.getRoot();
323 for(Element e : elements) {
330 public void setRenderingHint(Key arg0, Object arg1) {
331 if(G2DHints.KEY_BEGIN_ELEMENT == arg0) {
334 if(G2DHints.KEY_ELEMENT_ID == arg0) {
336 newElementId = arg1.toString();
338 newElementId = UUID.randomUUID().toString();
340 if(G2DHints.KEY_END_ELEMENT == arg0) {
343 Element group = getDOMFactory().createElementNS(SVG_NAMESPACE_URI, SVG_G_TAG);
344 group.setAttributeNS(null, "id", newElementId);
345 group.setAttributeNS(null, "class", arg1.toString());
350 super.setRenderingHint(arg0, arg1);
355 public static String renderSVG(ICanvasContext ctx) {
357 // Get a DOMImplementation.
358 DOMImplementation domImpl = GenericDOMImplementation.getDOMImplementation();
360 // Create an instance of org.w3c.dom.Document.
361 String svgNS = "http://www.w3.org/2000/svg";
362 Document document = domImpl.createDocument(svgNS, "svg", null);
364 // Create an instance of the SVG Generator.
365 SVGGraphics2D svgGenerator = new Generator(document);
369 G2DSceneGraph sg = ctx.getSceneGraph();
370 G2DParentNode root = (G2DParentNode) sg.getRootNode();
372 // rtree is the actual content of the diagram
373 RTreeNode rtree = NodeUtil.getNearestChildByClass(root, RTreeNode.class);
374 Rectangle2D rtreeBounds = NodeUtil.getLocalBounds(rtree);
376 // nav is a node that has zooming functionalities
377 NavigationNode nav = NodeUtil.getNearestChildByClass(root, NavigationNode.class);
378 nav.setZoomEnabled(true);
380 // fit view with the contents of rtreeBounds
381 nav.zoomTo(rtreeBounds);
383 // get the bounds of the content
384 Rectangle2D content = NodeUtil.getLocalBounds(nav);
386 // translate svgGenerator to the x and y coordinates of current content
387 svgGenerator.translate(-1 * content.getX(), -1 * content.getY());
389 Rectangle2D destination = new Rectangle2D.Double(0,0,1000,1000);
390 double sx = destination.getWidth() / content.getWidth();
391 double sy = destination.getHeight() / content.getHeight();
392 double scale = sx < sy ? sx : sy;
394 svgGenerator.scale(scale, scale);
396 // Set svgCanvasSize to the given size parameters
397 svgGenerator.setSVGCanvasSize(new Dimension((int)(scale * content.getWidth()), (int)(scale * content.getHeight())));
398 svgGenerator.setClip(content);
400 sg.render(svgGenerator);
407 // Finally, stream out SVG to the standard output using
409 boolean useCSS = true; // we want to use CSS style attributes
411 ByteArrayOutputStream os = new ByteArrayOutputStream();
412 Writer out = new OutputStreamWriter(os, "UTF-8");
413 svgGenerator.stream(out, useCSS);
416 result = new String(os.toByteArray());//Base64.encode(os.toByteArray());
417 } catch (UnsupportedEncodingException e) {
419 } catch (IOException e) {