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