comparison toolboxes/graph_visualisation/lib/lefty/dotty_layout.lefty @ 0:e9a9cd732c1e tip

first hg version after svn
author wolffd
date Tue, 10 Feb 2015 15:05:51 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:e9a9cd732c1e
1 #
2 # dotty_layout: layout functions and data structures
3 #
4 dotty.grablserver = function (lserver) {
5 local fd;
6
7 if (~dotty.lservers[lserver] | tablesize (dotty.lservers[lserver]) == 0) {
8 if (~((fd = openio ('pipe', lserver, 'r+', '%e -Txdot')) >= 0)) {
9 dotty.message (0, concat ('cannot start ', lserver));
10 return null;
11 }
12 dotty.lservers[lserver][fd] = [
13 'fd' = fd;
14 'count' = 0;
15 ];
16 }
17 for (fd in dotty.lservers[lserver]) {
18 dotty.lservers[lserver][fd].count = dotty.lservers[
19 lserver
20 ][fd].count + 1;
21 dotty.lservers.inuse[fd] = dotty.lservers[lserver][fd];
22 remove (fd, dotty.lservers[lserver]);
23 return fd;
24 }
25 };
26 dotty.releaselserver = function (lserver, fd, state) {
27 if (state == 'bad' | dotty.lservers.inuse[fd].count > 40) {
28 closeio (fd, 'kill');
29 remove (fd, dotty.lservers.inuse);
30 return;
31 }
32 dotty.lservers[lserver][fd] = dotty.lservers.inuse[fd];
33 remove (fd, dotty.lservers.inuse);
34 };
35 dotty.protogt.startlayout = function (gt) {
36 local lpt, fd;
37
38 if (gt.layoutpending >= 1) {
39 lpt = dotty.layoutpending[gt.gtid];
40 if (gt.layoutmode == 'async')
41 monitor ('off', lpt.fd);
42 dotty.releaselserver (gt.lserver, lpt.fd, 'bad');
43 remove (gt.gtid, dotty.layoutpending);
44 gt.layoutpending = 0;
45 gt.haveinput = 0;
46 dotty.popbusy (gt, gt.views);
47 }
48 if (~((fd = dotty.grablserver (gt.lserver)) >= 0))
49 return null;
50 dotty.pushbusy (gt, gt.views);
51 writegraph (fd, gt.graph, 1);
52 gt.layoutpending = 1;
53 dotty.layoutpending[gt.gtid] = [
54 'fd' = fd;
55 'gtid' = gt.gtid;
56 ];
57 if (gt.layoutmode == 'async')
58 monitor ('on', fd);
59 return 1;
60 };
61 dotty.protogt.finishlayout = function (gt) {
62 local graph, lpt, fd;
63
64 if (~(gt.layoutpending >= 1)) {
65 dotty.message (0, concat ('no layout pending for graph ', gt.gtid));
66 return null;
67 }
68 lpt = dotty.layoutpending[gt.gtid];
69 if (~(graph = readgraph (lpt.fd))) {
70 if (gt.layoutmode == 'async')
71 monitor ('off', lpt.fd);
72 dotty.releaselserver (gt.lserver, lpt.fd, 'bad');
73 if (gt.layoutpending == 2) {
74 dotty.message (0, concat ('giving up on ', gt.lserver));
75 if ((fd = openio ('file', 'dottybug.dot', 'w+')) >= 0) {
76 writegraph (fd, gt.graph, 0);
77 closeio (fd);
78 dotty.message (
79 0, concat ('graph that causes ', gt.lserver)
80 );
81 dotty.message (
82 0, 'to fail has been saved in file dottybug.dot'
83 );
84 dotty.message (
85 0, 'please fill out a bug report at'
86 );
87 dotty.message (
88 0, 'http://www.graphviz.org/bugs/bugform.html'
89 );
90 }
91 dotty.popbusy (gt, gt.views);
92 gt.layoutpending = 0;
93 gt.haveinput = 0;
94 return 1;
95 }
96 dotty.message (
97 1, concat ('lost connection to ', gt.lserver, ', restarting...')
98 );
99 lpt.fd = dotty.grablserver (gt.lserver);
100 writegraph (lpt.fd, gt.graph, 1);
101 if (gt.layoutmode == 'async')
102 monitor ('on', lpt.fd);
103 gt.layoutpending = 2;
104 gt.haveinput = 0;
105 return null;
106 }
107 if (gt.layoutmode == 'async')
108 monitor ('off', lpt.fd);
109 dotty.releaselserver (gt.lserver, lpt.fd, null);
110 remove (gt.gtid, dotty.layoutpending);
111 gt.layoutpending = 0;
112 gt.haveinput = 0;
113 gt.unpacklayout (gt, graph);
114 dotty.popbusy (gt, gt.views);
115 return 1;
116 };
117 dotty.protogt.cancellayout = function (gt) {
118 local lpt, vid;
119
120 if (gt.layoutpending >= 1) {
121 lpt = dotty.layoutpending[gt.gtid];
122 if (gt.layoutmode == 'async')
123 monitor ('off', lpt.fd);
124 dotty.releaselserver (gt.lserver, lpt.fd, 'bad');
125 remove (gt.gtid, dotty.layoutpending);
126 gt.layoutpending = 0;
127 gt.haveinput = 0;
128 dotty.popbusy (gt, gt.views);
129 }
130 };
131 dotty.protogt.unpacklayout = function (gt, graph2) {
132 local graph, gid, sgraph1, sgraph2, nid, node1, node2, eid, edge1, edge2;
133 local t1, pos, size;
134
135 graph = gt.graph;
136 for (gid in graph2.graphdict) {
137 if (~(sgraph1 = graph.graphs[graph.graphdict[gid]]))
138 continue;
139 sgraph2 = graph2.graphs[graph2.graphdict[gid]];
140 sgraph1.draws = gt.unpackalldraw (gt, sgraph2.graphattr);
141 }
142 for (nid in graph2.nodedict) {
143 if (~(node1 = graph.nodes[graph.nodedict[nid]]))
144 continue;
145 node2 = graph2.nodes[graph2.nodedict[nid]];
146 node1.draws = gt.unpackalldraw (gt, node2.attr);
147 t1 = split (node2.attr.pos, ',');
148 pos = ['x' = ston (t1[0]); 'y' = ston (t1[1]);];
149 size = [
150 'x' = ston (node2.attr.width) * 72;
151 'y' = ston (node2.attr.height) * 72;
152 ];
153 node1.pos = pos;
154 node1.size = size;
155 node1.rect = [
156 0 = ['x' = pos.x - size.x / 2; 'y' = pos.y - size.y / 2;];
157 1 = ['x' = pos.x + size.x / 2; 'y' = pos.y + size.y / 2;];
158 ];
159 }
160 for (eid in graph2.edges) {
161 edge2 = graph2.edges[eid];
162 if (edge2.attr.id) {
163 if (~(edge1 = graph.edges[ston (edge2.attr.id)]))
164 continue;
165 } else if (graph == graph2)
166 edge1 = edge2;
167 edge1.draws = gt.unpackalldraw (gt, edge2.attr);
168 }
169 graph.draws = gt.unpackalldraw (gt, graph2.graphattr);
170 t1 = split (graph2.graphattr.bb, ',');
171 graph.rect[0].x = ston (t1[0]);
172 graph.rect[0].y = ston (t1[1]);
173 graph.rect[1].x = ston (t1[2]);
174 graph.rect[1].y = ston (t1[3]);
175 if (gt.graph ~= graph2)
176 return;
177 # strip position and size info from the attributes
178 for (gid in graph2.graphdict) {
179 sgraph2 = graph2.graphs[graph2.graphdict[gid]];
180 gt.removealldraw (gt, sgraph2.graphattr);
181 if (sgraph2.graphattr.bb)
182 remove ('bb', sgraph2.graphattr);
183 }
184 for (nid in graph2.nodedict) {
185 node2 = graph2.nodes[graph2.nodedict[nid]];
186 gt.removealldraw (gt, node2.attr);
187 if (node2.attr.rects)
188 remove ('rects', node2.attr);
189 remove ('pos', node2.attr);
190 remove ('width', node2.attr);
191 remove ('height', node2.attr);
192 }
193 for (eid in graph2.edges) {
194 edge2 = graph2.edges[eid];
195 gt.removealldraw (gt, edge2.attr);
196 if (edge2.attr.pos)
197 remove ('pos', edge2.attr);
198 if (edge2.attr.lp)
199 remove ('lp', edge2.attr);
200 }
201 gt.removealldraw (gt, graph2.graphattr);
202 remove ('bb', graph2.graphattr);
203 if (graph2.graphattr.lp)
204 remove ('lp', graph2.graphattr);
205 };
206 #
207 # draw directive parsing
208 #
209 dotty.protogt.unpackalldraw = function (gt, attr) {
210 local o, did;
211
212 o = [];
213 if (attr._draw_)
214 o._draw_ = gt.unpackdraw (gt, attr._draw_);
215 if (attr._ldraw_)
216 o._ldraw_ = gt.unpackdraw (gt, attr._ldraw_);
217 if (attr._hdraw_)
218 o._hdraw_ = gt.unpackdraw (gt, attr._hdraw_);
219 if (attr._tdraw_)
220 o._tdraw_ = gt.unpackdraw (gt, attr._tdraw_);
221 if (attr._hldraw_)
222 o._hldraw_ = gt.unpackdraw (gt, attr._hldraw_);
223 if (attr._tldraw_)
224 o._tldraw_ = gt.unpackdraw (gt, attr._tldraw_);
225 for (did in o)
226 if (o[did].ep) {
227 o.ep = o[did].ep;
228 break;
229 }
230 return o;
231 };
232 dotty.protogt.removealldraw = function (gt, attr) {
233 if (attr._draw_)
234 remove ('_draw_', attr);
235 if (attr._ldraw_)
236 remove ('_ldraw_', attr);
237 if (attr._hdraw_)
238 remove ('_hdraw_', attr);
239 if (attr._tdraw_)
240 remove ('_tdraw_', attr);
241 if (attr._hldraw_)
242 remove ('_hldraw_', attr);
243 if (attr._tldraw_)
244 remove ('_tldraw_', attr);
245 };
246 dotty.protogt.unpackdraw = function (gt, attr) {
247 local oo, o, tt, t, n, i, j, s, l, ep;
248
249 oo = [];
250 t = split (attr, ' ', 0);
251 n = tablesize (t);
252 if (t[n - 1] == '') {
253 remove (n - 1, t);
254 n = n - 1;
255 }
256 i = 0;
257 while (i < n) {
258 o = [];
259 if (t[i] == 'E') {
260 o.type = t[i];
261 o.c.x = ston (t[i + 1]);
262 o.c.y = ston (t[i + 2]);
263 o.s.x = ston (t[i + 3]);
264 o.s.y = ston (t[i + 4]);
265 i = i + 5;
266 } else if (t[i] == 'e') {
267 o.type = t[i];
268 o.c.x = ston (t[i + 1]);
269 o.c.y = ston (t[i + 2]);
270 o.s.x = ston (t[i + 3]);
271 o.s.y = ston (t[i + 4]);
272 i = i + 5;
273 } else if (t[i] == 'P') {
274 o.type = t[i];
275 o.n = ston (t[i + 1]);
276 for (j = 0; j < o.n; j = j + 1) {
277 o.ps[j].x = ston (t[i + 2 + j * 2]);
278 o.ps[j].y = ston (t[i + 2 + j * 2 + 1]);
279 }
280 i = i + 2 + o.n * 2;
281 o.ps[o.n] = o.ps[0];
282 o.n = o.n + 1;
283 } else if (t[i] == 'p') {
284 o.type = t[i];
285 o.n = ston (t[i + 1]);
286 for (j = 0; j < o.n; j = j + 1) {
287 o.ps[j].x = ston (t[i + 2 + j * 2]);
288 o.ps[j].y = ston (t[i + 2 + j * 2 + 1]);
289 }
290 i = i + 2 + o.n * 2;
291 o.ps[o.n] = o.ps[0];
292 o.n = o.n + 1;
293 } else if (t[i] == 'L') {
294 o.type = t[i];
295 o.n = ston (t[i + 1]);
296 for (j = 0; j < o.n; j = j + 1) {
297 o.ps[j].x = ston (t[i + 2 + j * 2]);
298 o.ps[j].y = ston (t[i + 2 + j * 2 + 1]);
299 }
300 i = i + 2 + o.n * 2;
301 if (~ep)
302 ep = copy (o.ps[1]);
303 } else if (t[i] == 'B') {
304 o.type = t[i];
305 o.n = ston (t[i + 1]);
306 for (j = 0; j < o.n; j = j + 1) {
307 o.ps[j].x = ston (t[i + 2 + j * 2]);
308 o.ps[j].y = ston (t[i + 2 + j * 2 + 1]);
309 }
310 i = i + 2 + o.n * 2;
311 if (~ep)
312 ep = copy (o.ps[1]);
313 } else if (t[i] == 'b') {
314 o.type = t[i];
315 o.n = ston (t[i + 1]);
316 for (j = 0; j < o.n; j = j + 1) {
317 o.ps[j].x = ston (t[i + 2 + j * 2]);
318 o.ps[j].y = ston (t[i + 2 + j * 2 + 1]);
319 }
320 i = i + 2 + o.n * 2;
321 if (~ep)
322 ep = copy (o.ps[1]);
323 } else if (t[i] == 'T') {
324 o.type = t[i];
325 o.p.x = ston (t[i + 1]);
326 o.p.y = ston (t[i + 2]);
327 o.j = ston (t[i + 3]);
328 if (o.j == -1)
329 o.j = 'lb';
330 else if (o.j == 1)
331 o.j = 'rb';
332 else if (o.j == 0)
333 o.j = 'cb';
334 o.w = ston (t[i + 4]);
335 o.n = ston (t[i + 5]);
336 i = i + 6;
337 s = t[i];
338 i = i + 1;
339 l = strlen (s) - 1;
340 while (l < o.n) {
341 s = concat (s, ' ', t[i]);
342 l = l + 1 + strlen (t[i]);
343 i = i + 1;
344 }
345 tt = split (s, '');
346 l = tablesize (tt);
347 s = '';
348 for (j = 1; j < l; j = j + 1)
349 s = concat (s, tt[j]);
350 o.s = s;
351 } else if (t[i] == 'C') {
352 o.type = t[i];
353 o.n = ston (t[i + 1]);
354 i = i + 2;
355 s = t[i];
356 i = i + 1;
357 l = strlen (s) - 1;
358 while (l < o.n) {
359 s = concat (s, ' ', t[i]);
360 l = l + 1 + strlen (t[i]);
361 i = i + 1;
362 }
363 tt = split (s, '');
364 l = tablesize (tt);
365 s = '';
366 for (j = 1; j < l; j = j + 1)
367 s = concat (s, tt[j]);
368 o.fillcolor = gt.getcolor (gt.views, s);
369 } else if (t[i] == 'c') {
370 o.type = t[i];
371 o.n = ston (t[i + 1]);
372 i = i + 2;
373 s = t[i];
374 i = i + 1;
375 l = strlen (s) - 1;
376 while (l < o.n) {
377 s = concat (s, ' ', t[i]);
378 l = l + 1 + strlen (t[i]);
379 i = i + 1;
380 }
381 tt = split (s, '');
382 l = tablesize (tt);
383 s = '';
384 for (j = 1; j < l; j = j + 1)
385 s = concat (s, tt[j]);
386 o.drawcolor = gt.getcolor (gt.views, s);
387 } else if (t[i] == 'F') {
388 o.type = t[i];
389 o.fs = ston (t[i + 1]);
390 o.n = ston (t[i + 2]);
391 i = i + 3;
392 s = t[i];
393 i = i + 1;
394 l = strlen (s) - 1;
395 while (l < o.n) {
396 s = concat (s, ' ', t[i]);
397 l = l + 1 + strlen (t[i]);
398 i = i + 1;
399 }
400 tt = split (s, '');
401 l = tablesize (tt);
402 s = '';
403 for (j = 1; j < l; j = j + 1)
404 s = concat (s, tt[j]);
405 o.ofn = s;
406 o.fn = dotty.fontmap[s];
407 } else if (t[i] == 'S') {
408 o.type = t[i];
409 o.n = ston (t[i + 1]);
410 i = i + 2;
411 s = t[i];
412 i = i + 1;
413 l = strlen (s) - 1;
414 while (l < o.n) {
415 s = concat (s, ' ', t[i]);
416 l = l + 1 + strlen (t[i]);
417 i = i + 1;
418 }
419 tt = split (s, '');
420 l = tablesize (tt);
421 s = '';
422 for (j = 1; j < l; j = j + 1)
423 s = concat (s, tt[j]);
424 if (
425 s == 'solid' | s == 'dashed' | s == 'dotted' |
426 s == 'longdashed' | s == 'shortdashed'
427 )
428 o.style = s;
429 else if (s == 'bold')
430 o.width = 3;
431 else {
432 tt = split (s, '(');
433 if (tt[0] == 'setlinewidth') {
434 tt = split (tt[1], ')');
435 o.width = ston (tt[0]);
436 } else
437 continue;
438 }
439 } else if (t[i] == 'I') {
440 i = i + 7;
441 } else {
442 dotty.message (0, concat ('draw language parser error: ', t[i]));
443 return null;
444 }
445 oo[tablesize (oo)] = o;
446 }
447 oo.ep = ep;
448 return oo;
449 };