]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.graphviz/src/org/simantics/graphviz/drawable/GraphDrawable2.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.graphviz / src / org / simantics / graphviz / drawable / GraphDrawable2.java
diff --git a/bundles/org.simantics.graphviz/src/org/simantics/graphviz/drawable/GraphDrawable2.java b/bundles/org.simantics.graphviz/src/org/simantics/graphviz/drawable/GraphDrawable2.java
new file mode 100644 (file)
index 0000000..edba7ce
--- /dev/null
@@ -0,0 +1,207 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.graphviz.drawable;\r
+\r
+import java.awt.Graphics2D;\r
+import java.awt.Shape;\r
+import java.awt.geom.Point2D;\r
+import java.awt.geom.Rectangle2D;\r
+import java.io.IOException;\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.HashMap;\r
+import java.util.Map;\r
+import java.util.concurrent.ExecutionException;\r
+\r
+import org.simantics.graphviz.Edge;\r
+import org.simantics.graphviz.Graph;\r
+import org.simantics.graphviz.Graphs;\r
+import org.simantics.graphviz.IGraphPart;\r
+import org.simantics.graphviz.Identifiable;\r
+import org.simantics.graphviz.continuation.Computation;\r
+import org.simantics.graphviz.continuation.Continuation;\r
+import org.simantics.graphviz.internal.parser.ParseException;\r
+import org.simantics.graphviz.internal.xdot.DrawCommand;\r
+import org.simantics.graphviz.internal.xdot.DrawCommandParser;\r
+import org.simantics.graphviz.internal.xdot.ShapeCommand;\r
+\r
+/**\r
+ * A drawable that draws a given graph.\r
+ * Supports picking elements.\r
+ * \r
+ * TODO: optimize, uses hashmaps in places where those are not useful. \r
+ * \r
+ * \r
+ * @author Hannu Niemist�\r
+ * @author Marko Luukkainen\r
+ */\r
+public class GraphDrawable2 implements Drawable {\r
+\r
+       private static String DEFAULT_ALGORITHM = "dot";\r
+       \r
+       Collection<DrawCommand> commands;\r
+       Map<IGraphPart,Collection<DrawCommand>> partCommands;\r
+       Map<IGraphPart,Rectangle2D> partBounds;\r
+       \r
+       Rectangle2D bounds;\r
+       \r
+       public GraphDrawable2(Graph graph, String algorithm) {\r
+               try {\r
+            setGraph(graph, algorithm).get();\r
+        } catch (Exception e) {\r
+            e.printStackTrace();\r
+        }\r
+       }\r
+       \r
+       public GraphDrawable2(Graph graph) {\r
+               setGraph(graph);\r
+       }\r
+       \r
+       public GraphDrawable2() {\r
+               commands = new ArrayList<DrawCommand>();\r
+               partCommands = new HashMap<IGraphPart, Collection<DrawCommand>>();\r
+               partBounds = new HashMap<IGraphPart, Rectangle2D>();\r
+               bounds = new Rectangle2D.Double(0, 0, 100, 100);\r
+       }\r
+       \r
+       /**\r
+        * Sets a new graph to be drawn. This operation may take a while. It can\r
+        * be called from any thread.\r
+        * @param graph\r
+        */\r
+       public void setGraph(Graph graph) {\r
+           try {\r
+               setGraph(graph, DEFAULT_ALGORITHM).get();\r
+           } catch(Exception e) {\r
+               e.printStackTrace();\r
+           }\r
+       }\r
+       \r
+       \r
+       \r
+       /**\r
+        * Sets a new graph to be drawn. This operation may take a while. It can\r
+        * be called from any thread.\r
+        * @param graph\r
+        */\r
+       public synchronized Computation<Graph> setGraph(final Graph graph, String algorithm) {\r
+           Computation<Graph> computation = Graphs.createXDot(graph, algorithm);\r
+           computation.addContinuation(new Continuation<Graph>() {\r
+            @Override\r
+            public void succeeded(Graph xgraph) {\r
+                commands = new ArrayList<DrawCommand>();\r
+                partCommands = new HashMap<IGraphPart, Collection<DrawCommand>>();\r
+                partBounds = new HashMap<IGraphPart, Rectangle2D>();\r
+                DrawCommandParser.parse(xgraph,commands,partCommands);\r
+                readBoundingBox(xgraph);\r
+                updatePartBoundingBoxes(graph, xgraph);\r
+            }\r
+\r
+            @Override\r
+            public void failed(Exception exception) {\r
+            }\r
+           });\r
+           return computation;\r
+       }\r
+       \r
+       private void readBoundingBox(Graph graph) {\r
+               String[] parts = graph.get("bb").split(",");\r
+               double minX = Double.parseDouble(parts[0]);\r
+               double maxY = -Double.parseDouble(parts[1]);\r
+               double maxX = Double.parseDouble(parts[2]);\r
+               double minY = -Double.parseDouble(parts[3]);\r
+               bounds = new Rectangle2D.Double(minX, minY, maxX-minX, maxY-minY);\r
+       }\r
+       \r
+       private void updatePartBoundingBoxes(Graph graph, Graph xgraph) {\r
+               // we have to map input Nodes to XGraph nodes\r
+               \r
+               Map<IGraphPart,IGraphPart> partMap = new HashMap<IGraphPart, IGraphPart>();\r
+           \r
+               for (IGraphPart xPart : xgraph.getParts()) {\r
+                       if (xPart instanceof Identifiable) {\r
+                               String xID = ((Identifiable)xPart).getId();\r
+                               for (IGraphPart gPart : graph.getParts()) {\r
+                                       if (gPart instanceof Identifiable) {\r
+                                               String gID = ((Identifiable)gPart).getId();\r
+                                               if (xID.equals(gID)) {\r
+                                                       partMap.put(xPart, gPart);\r
+                                               }\r
+                                       }\r
+                               }\r
+                       } else if (xPart instanceof Edge) {\r
+                               String xHeadId = ((Edge)xPart).getHead().getId();\r
+                               String xTailId = ((Edge)xPart).getTail().getId();\r
+                               for (IGraphPart gPart : graph.getParts()) {\r
+                                       if (gPart instanceof Edge) {\r
+                                               String gHeadId = ((Edge)gPart).getHead().getId();\r
+                                               String gTailId = ((Edge)gPart).getTail().getId();\r
+                                               \r
+                                               if (xHeadId.equals(gHeadId) && xTailId.equals(gTailId)) {\r
+                                                       partMap.put(xPart, gPart);\r
+                                               }\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+               \r
+               \r
+           \r
+               for (IGraphPart part : partCommands.keySet()) {\r
+                       Collection<DrawCommand> pCommands = partCommands.get(part);\r
+                       Rectangle2D r = null;\r
+                       for (DrawCommand c : pCommands) {\r
+                               if (c instanceof ShapeCommand) {\r
+                                       Shape s = ((ShapeCommand)c).getShape();\r
+                                       if (r == null)\r
+                                               r = s.getBounds2D();\r
+                                       else\r
+                                               r.add(s.getBounds2D());\r
+                               }\r
+                       }\r
+                       if (r != null) {\r
+                               partBounds.put(partMap.get(part), r);\r
+                       }\r
+               }\r
+       }\r
+       \r
+       @Override\r
+       public synchronized Rectangle2D getBounds() {\r
+               return bounds;\r
+       }\r
+       \r
+       \r
+       public synchronized Rectangle2D getBounds(IGraphPart part) {\r
+               return partBounds.get(part);\r
+       }\r
+       \r
+       public synchronized Collection<IGraphPart> pick(Point2D point) {\r
+               Collection<IGraphPart> picked = new ArrayList<IGraphPart>();\r
+               for (IGraphPart part : partBounds.keySet()) {\r
+                       Rectangle2D r = partBounds.get(part);\r
+                       if (r.contains(point))\r
+                               picked.add(part);\r
+               }\r
+               return picked;\r
+       }\r
+       \r
+       @Override\r
+       public synchronized void draw(Graphics2D g, Rectangle2D area) {\r
+               for(DrawCommand command : commands)\r
+                       command.draw(g);\r
+               \r
+//             for (Rectangle2D r : partBounds.values()) {\r
+//                     g.drawRect((int)r.getMinX(), (int)r.getMinY(), (int)r.getWidth(), (int)r.getHeight());\r
+//             }\r
+       }\r
+       \r
+}\r