]> gerrit.simantics Code Review - simantics/platform.git/blob - 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
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
3  * in Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.graphviz.drawable;\r
13 \r
14 import java.awt.Graphics2D;\r
15 import java.awt.Shape;\r
16 import java.awt.geom.Point2D;\r
17 import java.awt.geom.Rectangle2D;\r
18 import java.io.IOException;\r
19 import java.util.ArrayList;\r
20 import java.util.Collection;\r
21 import java.util.HashMap;\r
22 import java.util.Map;\r
23 import java.util.concurrent.ExecutionException;\r
24 \r
25 import org.simantics.graphviz.Edge;\r
26 import org.simantics.graphviz.Graph;\r
27 import org.simantics.graphviz.Graphs;\r
28 import org.simantics.graphviz.IGraphPart;\r
29 import org.simantics.graphviz.Identifiable;\r
30 import org.simantics.graphviz.continuation.Computation;\r
31 import org.simantics.graphviz.continuation.Continuation;\r
32 import org.simantics.graphviz.internal.parser.ParseException;\r
33 import org.simantics.graphviz.internal.xdot.DrawCommand;\r
34 import org.simantics.graphviz.internal.xdot.DrawCommandParser;\r
35 import org.simantics.graphviz.internal.xdot.ShapeCommand;\r
36 \r
37 /**\r
38  * A drawable that draws a given graph.\r
39  * Supports picking elements.\r
40  * \r
41  * TODO: optimize, uses hashmaps in places where those are not useful. \r
42  * \r
43  * \r
44  * @author Hannu Niemist�\r
45  * @author Marko Luukkainen\r
46  */\r
47 public class GraphDrawable2 implements Drawable {\r
48 \r
49         private static String DEFAULT_ALGORITHM = "dot";\r
50         \r
51         Collection<DrawCommand> commands;\r
52         Map<IGraphPart,Collection<DrawCommand>> partCommands;\r
53         Map<IGraphPart,Rectangle2D> partBounds;\r
54         \r
55         Rectangle2D bounds;\r
56         \r
57         public GraphDrawable2(Graph graph, String algorithm) {\r
58                 try {\r
59             setGraph(graph, algorithm).get();\r
60         } catch (Exception e) {\r
61             e.printStackTrace();\r
62         }\r
63         }\r
64         \r
65         public GraphDrawable2(Graph graph) {\r
66                 setGraph(graph);\r
67         }\r
68         \r
69         public GraphDrawable2() {\r
70                 commands = new ArrayList<DrawCommand>();\r
71                 partCommands = new HashMap<IGraphPart, Collection<DrawCommand>>();\r
72                 partBounds = new HashMap<IGraphPart, Rectangle2D>();\r
73                 bounds = new Rectangle2D.Double(0, 0, 100, 100);\r
74         }\r
75         \r
76         /**\r
77          * Sets a new graph to be drawn. This operation may take a while. It can\r
78          * be called from any thread.\r
79          * @param graph\r
80          */\r
81         public void setGraph(Graph graph) {\r
82             try {\r
83                 setGraph(graph, DEFAULT_ALGORITHM).get();\r
84             } catch(Exception e) {\r
85                 e.printStackTrace();\r
86             }\r
87         }\r
88         \r
89         \r
90         \r
91         /**\r
92          * Sets a new graph to be drawn. This operation may take a while. It can\r
93          * be called from any thread.\r
94          * @param graph\r
95          */\r
96         public synchronized Computation<Graph> setGraph(final Graph graph, String algorithm) {\r
97             Computation<Graph> computation = Graphs.createXDot(graph, algorithm);\r
98             computation.addContinuation(new Continuation<Graph>() {\r
99             @Override\r
100             public void succeeded(Graph xgraph) {\r
101                 commands = new ArrayList<DrawCommand>();\r
102                 partCommands = new HashMap<IGraphPart, Collection<DrawCommand>>();\r
103                 partBounds = new HashMap<IGraphPart, Rectangle2D>();\r
104                 DrawCommandParser.parse(xgraph,commands,partCommands);\r
105                 readBoundingBox(xgraph);\r
106                 updatePartBoundingBoxes(graph, xgraph);\r
107             }\r
108 \r
109             @Override\r
110             public void failed(Exception exception) {\r
111             }\r
112             });\r
113             return computation;\r
114         }\r
115         \r
116         private void readBoundingBox(Graph graph) {\r
117                 String[] parts = graph.get("bb").split(",");\r
118                 double minX = Double.parseDouble(parts[0]);\r
119                 double maxY = -Double.parseDouble(parts[1]);\r
120                 double maxX = Double.parseDouble(parts[2]);\r
121                 double minY = -Double.parseDouble(parts[3]);\r
122                 bounds = new Rectangle2D.Double(minX, minY, maxX-minX, maxY-minY);\r
123         }\r
124         \r
125         private void updatePartBoundingBoxes(Graph graph, Graph xgraph) {\r
126                 // we have to map input Nodes to XGraph nodes\r
127                 \r
128                 Map<IGraphPart,IGraphPart> partMap = new HashMap<IGraphPart, IGraphPart>();\r
129             \r
130                 for (IGraphPart xPart : xgraph.getParts()) {\r
131                         if (xPart instanceof Identifiable) {\r
132                                 String xID = ((Identifiable)xPart).getId();\r
133                                 for (IGraphPart gPart : graph.getParts()) {\r
134                                         if (gPart instanceof Identifiable) {\r
135                                                 String gID = ((Identifiable)gPart).getId();\r
136                                                 if (xID.equals(gID)) {\r
137                                                         partMap.put(xPart, gPart);\r
138                                                 }\r
139                                         }\r
140                                 }\r
141                         } else if (xPart instanceof Edge) {\r
142                                 String xHeadId = ((Edge)xPart).getHead().getId();\r
143                                 String xTailId = ((Edge)xPart).getTail().getId();\r
144                                 for (IGraphPart gPart : graph.getParts()) {\r
145                                         if (gPart instanceof Edge) {\r
146                                                 String gHeadId = ((Edge)gPart).getHead().getId();\r
147                                                 String gTailId = ((Edge)gPart).getTail().getId();\r
148                                                 \r
149                                                 if (xHeadId.equals(gHeadId) && xTailId.equals(gTailId)) {\r
150                                                         partMap.put(xPart, gPart);\r
151                                                 }\r
152                                         }\r
153                                 }\r
154                         }\r
155                 }\r
156                 \r
157                 \r
158             \r
159                 for (IGraphPart part : partCommands.keySet()) {\r
160                         Collection<DrawCommand> pCommands = partCommands.get(part);\r
161                         Rectangle2D r = null;\r
162                         for (DrawCommand c : pCommands) {\r
163                                 if (c instanceof ShapeCommand) {\r
164                                         Shape s = ((ShapeCommand)c).getShape();\r
165                                         if (r == null)\r
166                                                 r = s.getBounds2D();\r
167                                         else\r
168                                                 r.add(s.getBounds2D());\r
169                                 }\r
170                         }\r
171                         if (r != null) {\r
172                                 partBounds.put(partMap.get(part), r);\r
173                         }\r
174                 }\r
175         }\r
176         \r
177         @Override\r
178         public synchronized Rectangle2D getBounds() {\r
179                 return bounds;\r
180         }\r
181         \r
182         \r
183         public synchronized Rectangle2D getBounds(IGraphPart part) {\r
184                 return partBounds.get(part);\r
185         }\r
186         \r
187         public synchronized Collection<IGraphPart> pick(Point2D point) {\r
188                 Collection<IGraphPart> picked = new ArrayList<IGraphPart>();\r
189                 for (IGraphPart part : partBounds.keySet()) {\r
190                         Rectangle2D r = partBounds.get(part);\r
191                         if (r.contains(point))\r
192                                 picked.add(part);\r
193                 }\r
194                 return picked;\r
195         }\r
196         \r
197         @Override\r
198         public synchronized void draw(Graphics2D g, Rectangle2D area) {\r
199                 for(DrawCommand command : commands)\r
200                         command.draw(g);\r
201                 \r
202 //              for (Rectangle2D r : partBounds.values()) {\r
203 //                      g.drawRect((int)r.getMinX(), (int)r.getMinY(), (int)r.getWidth(), (int)r.getHeight());\r
204 //              }\r
205         }\r
206         \r
207 }\r