1
2
3
4
5
6 package net.kwfgrid.gwui.graphviz;
7
8 import org.glassbox.dotparser.*;
9
10 import java.awt.*;
11 import java.util.HashMap;
12
13 /***
14 Very basic implementation of a layout builder.
15 This is the counterpart of <code>WorkflowGraph2DOTConverter</code> and the <code>LayoutBuilder</code>
16 does only support the features which are required for a dot file which has been generated with
17 <code>WorkflowGraph2DOTConverter</code> and then attributed by graphviz' dot layouter.
18 */
19 public class LayoutBuilder implements DOTParserVisitor {
20 /*** The screen resolution. */
21 public static final int DPI = 72;
22
23 private HashMap _nodepositions;
24 private HashMap _edgelines;
25 private HashMap _edgelabelpositions;
26 private boolean _node_stmt;
27 private boolean _graph_attr_stmt;
28 private boolean _edge_stmt;
29 private String _node_id;
30 private String _from_node_id;
31 private String _to_node_id;
32 private Rectangle _graph_bb;
33
34 public LayoutBuilder() {
35 _nodepositions = new HashMap();
36 _edgelines = new HashMap();
37 _edgelabelpositions = new HashMap();
38 _graph_bb = null;
39 _graph_attr_stmt = false;
40 _node_stmt = false;
41 _edge_stmt = false;
42 _node_id = null;
43 _from_node_id = null;
44 _to_node_id = null;
45 }
46
47 /***
48 Create an edge ID from two node ids.
49 */
50 protected String edgeID(String fromnodeid, String tonodeid) {
51 return fromnodeid + "->" +tonodeid;
52 }
53
54 /***
55 Ignored.
56 @return <code>null<code>.
57 */
58 public Object visit(SimpleNode node, Object data) {
59 return null;
60 }
61
62 /***
63 @return <code>null<code>.
64 */
65 public Object visit(ASTgraph node, Object data) {
66 _node_stmt = false;
67 _graph_attr_stmt = false;
68 _edge_stmt = false;
69 return null;
70 }
71
72 /***
73 Ignored.
74 @return <code>null<code>.
75 */
76 public Object visit(ASTstmt_list node, Object data) {
77 _node_stmt = false;
78 _graph_attr_stmt = false;
79 _edge_stmt = false;
80 return null;
81 }
82
83 /***
84 Ignored.
85 @return <code>null<code>.
86 */
87 public Object visit(ASTstmt node, Object data) {
88 _node_stmt = false;
89 _graph_attr_stmt = false;
90 _edge_stmt = false;
91 return null;
92 }
93
94 /***
95 Ignored.
96 @return <code>null<code>.
97 */
98 public Object visit(ASTideq_stmt node, Object data) {
99 return null;
100 }
101
102 /***
103 Ignored.
104 @return <code>null<code>.
105 */
106 public Object visit(ASTattr_stmt node, Object data) {
107 if (node.isGraphStatement()) {
108 _graph_attr_stmt = true;
109 }
110 return null;
111 }
112
113 /***
114 @return <code>null<code>.
115 */
116 public Object visit(ASTnode_stmt node, Object data) {
117 _node_stmt = true;
118 return null;
119 }
120
121 /***
122 @return <code>null<code>.
123 */
124 public Object visit(ASTnode_id node, Object data) {
125 if (_node_stmt) {
126 _node_id = node.getID();
127 } else if (_edge_stmt) {
128 if (_from_node_id == null)
129 _from_node_id = node.getID();
130 else
131 _to_node_id = node.getID();
132 }
133 return null;
134 }
135
136 /***
137 @return <code>null<code>.
138 */
139 public Object visit(ASTport node, Object data) {
140 return null;
141 }
142
143 /***
144 @return <code>null<code>.
145 */
146 public Object visit(ASTcompass_pt node, Object data) {
147 return null;
148 }
149
150 /***
151 @return <code>null<code>.
152 */
153 public Object visit(ASTedge_stmt node, Object data) {
154 _edge_stmt = true;
155 _from_node_id = null;
156 _to_node_id = null;
157 return null;
158 }
159
160 /***
161 @return <code>null<code>.
162 */
163 public Object visit(ASTsubgraph node, Object data) {
164 return null;
165 }
166
167 /***
168 @return <code>null<code>.
169 */
170 public Object visit(ASTedgeRHS node, Object data) {
171 return null;
172 }
173
174 /***
175 @return <code>null<code>.
176 */
177 public Object visit(ASTedgeop node, Object data) {
178 return null;
179 }
180
181 /***
182 @return <code>null<code>.
183 */
184 public Object visit(ASTattr_list node, Object data) {
185 return null;
186 }
187
188 /***
189 @return <code>null<code>.
190 */
191 public Object visit(ASTa_list node, Object data) {
192 String key = node.getKey();
193 String value = node.getValue();
194 if (_node_stmt) {
195 if (DOTNodeAttributes.POS.equals(key)) {
196 _nodepositions.put(_node_id, DOTAttributeUtilities.point(value));
197 }
198 } else if (_graph_attr_stmt) {
199 if (DOTGraphAttributes.BB.equals(key) && !"".equals(value)) {
200 _graph_bb = DOTAttributeUtilities.rectangle(value);
201 }
202 } else if (_edge_stmt) {
203 if (_from_node_id != null && _to_node_id != null) {
204 if (DOTEdgeAttributes.POS.equals(key)) {
205 _edgelines.put(edgeID(_from_node_id, _to_node_id), DOTAttributeUtilities.edge(value));
206 } else if (DOTEdgeAttributes.LP.equals(key)) {
207 _edgelabelpositions.put(edgeID(_from_node_id, _to_node_id), DOTAttributeUtilities.point(value));
208 }
209 }
210 }
211 return null;
212 }
213
214 /***
215 Get the pixel position of a node.
216 */
217 public Point getNodePosition(String nodeid) {
218 return (Point)_nodepositions.get(nodeid);
219 }
220
221 /***
222 Get the bounding box of the graph.
223 */
224 public Rectangle getGraphBoundingBox() {
225 return _graph_bb;
226 }
227
228 /***
229 Get the control points of an edge.
230 @param fromnodeid The id of the from-node of the edge.
231 @param tonodeid The id of the to-node of the edge.
232 */
233 public Point[] getEdgeControlPoints(String fromnodeid, String tonodeid) {
234 DOTLine line = (DOTLine)_edgelines.get(edgeID(fromnodeid, tonodeid));
235 if (line != null)
236 return line.getControlPoints();
237 else
238 return null;
239 }
240
241 /***
242 Get the point of the arrow at the edge's head.(<code>null</code> if the edge does not have an arrow at it's head.)
243 @param fromnodeid The id of the from-node of the edge.
244 @param tonodeid The id of the to-node of the edge.
245 */
246 public Point getEdgePointOfArrowAtStart(String fromnodeid, String tonodeid) {
247 DOTLine line = (DOTLine)_edgelines.get(edgeID(fromnodeid, tonodeid));
248 if (line != null)
249 return line.getPointOfArrowAtStart();
250 else
251 return null;
252 }
253
254 /***
255 Get the point of the arrow at the edge's tail. (<code>null</code> if the edge does not have an arrow at it's tail.)
256 @param fromnodeid The id of the from-node of the edge.
257 @param tonodeid The id of the to-node of the edge.
258 */
259 public Point getEdgePointOfArrowAtEnd(String fromnodeid, String tonodeid) {
260 DOTLine line = (DOTLine)_edgelines.get(edgeID(fromnodeid, tonodeid));
261 if (line != null)
262 return line.getPointOfArrowAtEnd();
263 else
264 return null;
265 }
266
267 /***
268 Check if the edge has an arrow at it's head.
269 @param fromnodeid The id of the from-node of the edge.
270 @param tonodeid The id of the to-node of the edge.
271 */
272 public boolean hasEdgeArrowAtStart(String fromnodeid, String tonodeid) {
273 DOTLine line = (DOTLine)_edgelines.get(edgeID(fromnodeid, tonodeid));
274 if (line != null)
275 return line.hasArrowAtStart();
276 else
277 return false;
278 }
279
280 /***
281 Check if the edge has an arrow at it's tail.
282 @param fromnodeid The id of the from-node of the edge.
283 @param tonodeid The id of the to-node of the edge.
284 */
285 public boolean hasEdgeArrowAtEnd(String fromnodeid, String tonodeid) {
286 DOTLine line = (DOTLine)_edgelines.get(edgeID(fromnodeid, tonodeid));
287 if (line != null)
288 return line.hasArrowAtEnd();
289 else
290 return false;
291 }
292
293 /***
294 Get the position of an edge's label.
295 @param fromnodeid The id of the from-node of the edge.
296 @param tonodeid The id of the to-node of the edge.
297 */
298 public Point getEdgeLabelPosition(String fromnodeid, String tonodeid) {
299 return (Point)_edgelabelpositions.get(edgeID(fromnodeid, tonodeid));
300 }
301 }