Mercurial > hg > camir-aes2014
comparison toolboxes/graph_visualisation/lib/lefty/dotty.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 | |
3 # | |
4 dotty = [ | |
5 'keys' = [ | |
6 'nid' = 'nid'; | |
7 'eid' = 'eid'; | |
8 'gid' = 'gid'; | |
9 'name' = 'name'; | |
10 'attr' = 'attr'; | |
11 'gattr' = 'graphattr'; | |
12 'eattr' = 'edgeattr'; | |
13 'nattr' = 'nodeattr'; | |
14 'edges' = 'edges'; | |
15 'tail' = 'tail'; | |
16 'tport' = 'tport'; | |
17 'head' = 'head'; | |
18 'hport' = 'hport'; | |
19 'pos' = 'pos'; | |
20 'size' = 'size'; | |
21 'rect' = 'rect'; | |
22 'fname' = 'fontname'; | |
23 'fsize' = 'fontsize'; | |
24 'fcolor' = 'fontcolor'; | |
25 'dcolor' = 'drawcolor'; | |
26 'bcolor' = 'fillcolor'; | |
27 ]; | |
28 'maps' = [ | |
29 'X11' = [ | |
30 'fontmap' = [ | |
31 'Times-Roman' = '-*-times-medium-r-*--%d-*-*-*-*-*-*-1'; | |
32 'Times-Italic' = '-*-times-medium-i-*--%d-*-*-*-*-*-*-1'; | |
33 'Times-Bold' = '-*-times-bold-r-*--%d-*-*-*-*-*-*-1'; | |
34 'Courier' = '-*-courier-bold-r-*--%d-*-*-*-*-*-*-1'; | |
35 'Courier-Bold' = '-*-courier-bold-r-*--%d-*-*-*-*-*-*-1'; | |
36 'Helvetica' = ( | |
37 '-*-helvetica-medium-r-normal--%d-*-*-*-p-*-iso8859-1' | |
38 ); | |
39 'Helvetica-Bold' = ( | |
40 '-*-helvetica-bold-r-normal--%d-*-*-*-p-*-iso8859-1' | |
41 ); | |
42 ]; | |
43 'psfontmap' = [ | |
44 'Times-Roman' = 'Times-Roman'; | |
45 'Times-Italic' = 'Times-Italic'; | |
46 'Times-Bold' = 'Times-Bold'; | |
47 'Courier' = 'Courier'; | |
48 'Courier-Bold' = 'Courier-Bold'; | |
49 'Helvetica' = 'Helvetica'; | |
50 'Helvetica-Bold' = 'Helvetica-Bold'; | |
51 ]; | |
52 ]; | |
53 'mswin' = [ | |
54 'fontmap' = [ | |
55 'Times-Roman' = 'Times New Roman'; | |
56 'Times-Italic' = 'Times New Roman Italic'; | |
57 'Times-Bold' = 'Times New Roman Bold'; | |
58 'Courier' = 'Courier New'; | |
59 'Courier-Bold' = 'Courier New Bold'; | |
60 'Helvetica' = 'Arial'; | |
61 'Helvetica-Bold' = 'Arial Bold'; | |
62 ]; | |
63 'psfontmap' = [ | |
64 'Times-Roman' = 'Times New Roman'; | |
65 'Times-Italic' = 'Times New Roman Italic'; | |
66 'Times-Bold' = 'Times New Roman Bold'; | |
67 'Courier' = 'Courier New'; | |
68 'Courier-Bold' = 'Courier New Bold'; | |
69 'Helvetica' = 'Arial'; | |
70 'Helvetica-Bold' = 'Arial Bold'; | |
71 ]; | |
72 ]; | |
73 ]; | |
74 'protogt' = [ | |
75 'graph' = [ | |
76 'graphattr' = [ | |
77 'fontsize' = '14'; | |
78 'fontname' = 'Times-Roman'; | |
79 'fontcolor' = 'black'; | |
80 ]; | |
81 'nodeattr' = [ | |
82 'shape' = 'ellipse'; | |
83 'fontsize' = '14'; | |
84 'fontname' = 'Times-Roman'; | |
85 'fontcolor' = 'black'; | |
86 'style' = 'solid'; | |
87 ]; | |
88 'edgeattr' = [ | |
89 'fontsize' = '14'; | |
90 'fontname' = 'Times-Roman'; | |
91 'fontcolor' = 'black'; | |
92 'style' = 'solid'; | |
93 ]; | |
94 'graphdict' = []; | |
95 'nodedict' = []; | |
96 'graphs' = []; | |
97 'nodes' = []; | |
98 'edges' = []; | |
99 'maxgid' = 0; | |
100 'maxnid' = 0; | |
101 'maxeid' = 0; | |
102 'type' = 'digraph'; | |
103 ]; | |
104 'layoutmode' = 'sync'; | |
105 'lserver' = 'dot'; | |
106 'edgehandles' = 1; | |
107 'noundo' = 0; | |
108 ]; | |
109 'lservers' = []; | |
110 'mlevel' = 0; | |
111 'graphs' = []; | |
112 'views' = []; | |
113 'protovt' = [ | |
114 'normal' = [ | |
115 'name' = 'DOTTY'; | |
116 'orig' = ['x' = 1; 'y' = 1;]; | |
117 'size' = ['x' = 420; 'y' = 520;]; | |
118 'wrect' = [ | |
119 0 = ['x' = 0; 'y' = 0;]; | |
120 1 = ['x' = 400; 'y' = 500;]; | |
121 ]; | |
122 'vsize' = ['x' = 400; 'y' = 500;]; | |
123 'w2v' = 1; | |
124 ]; | |
125 'birdseye' = [ | |
126 'type' = 'birdseye'; | |
127 'name' = 'DOTTY birdseye view'; | |
128 'orig' = ['x' = 1; 'y' = 1;]; | |
129 'size' = ['x' = 220; 'y' = 260;]; | |
130 'wrect' = [ | |
131 0 = ['x' = 0; 'y' = 0;]; | |
132 1 = ['x' = 200; 'y' = 250;]; | |
133 ]; | |
134 'vsize' = ['x' = 200; 'y' = 250;]; | |
135 'w2v' = 1; | |
136 ]; | |
137 ]; | |
138 'pagesizes' = [ | |
139 '8.5x11' = ['x' = 8; 'y' = 10.5;]; | |
140 '11x17' = ['x' = 10.5; 'y' = 16.5;]; | |
141 '36x50' = ['x' = 35.5; 'y' = 49.5;]; | |
142 ]; | |
143 ]; | |
144 load ('dotty_draw.lefty'); | |
145 load ('dotty_edit.lefty'); | |
146 load ('dotty_layout.lefty'); | |
147 load ('dotty_ui.lefty'); | |
148 # | |
149 # initialization functions | |
150 # | |
151 dotty.init = function () { | |
152 dotty.fontmap = dotty.maps[getenv ('LEFTYWINSYS')].fontmap; | |
153 dotty.clipgt = dotty.protogt.creategraph (['noundo' = 1;]); | |
154 dotty.inited = 1; | |
155 }; | |
156 dotty.simple = function (file) { | |
157 if (dotty.inited ~= 1) | |
158 dotty.init (); | |
159 dotty.createviewandgraph (file, 'file', null, null); | |
160 txtview ('off'); | |
161 }; | |
162 # | |
163 # main operations | |
164 # | |
165 dotty.protogt.creategraph = function (protogt) { | |
166 local gt, id, gtid; | |
167 | |
168 if (~protogt) | |
169 protogt = dotty.protogt; | |
170 for (gtid = 0; dotty.graphs[gtid]; gtid = gtid + 1) | |
171 ; | |
172 gt = (dotty.graphs[gtid] = []); | |
173 if (protogt.mode ~= 'replace') { | |
174 for (id in dotty.protogt) | |
175 gt[id] = copy (dotty.protogt[id]); | |
176 } | |
177 for (id in protogt) | |
178 gt[id] = copy (protogt[id]); | |
179 gt.gtid = gtid; | |
180 gt.views = []; | |
181 gt.undoarray = ['level' = 0; 'entries' = [];]; | |
182 gt.busy = 0; | |
183 return gt; | |
184 }; | |
185 dotty.protogt.copygraph = function (ogt) { | |
186 local gt, gtid, id; | |
187 | |
188 for (gtid = 0; dotty.graphs[gtid]; gtid = gtid + 1) | |
189 ; | |
190 gt = (dotty.graphs[gtid] = []); | |
191 for (id in ogt) | |
192 gt[id] = copy (ogt[id]); | |
193 gt.gtid = gtid; | |
194 gt.views = []; | |
195 gt.undoarray = ['level' = 0; 'entries' = [];]; | |
196 gt.busy = 0; | |
197 return gt; | |
198 }; | |
199 dotty.protogt.destroygraph = function (gt) { | |
200 local vid, vlist; | |
201 | |
202 if (gt.layoutpending > 0) | |
203 gt.cancellayout (gt); | |
204 for (vid in gt.views) | |
205 vlist[vid] = gt.views[vid]; | |
206 for (vid in gt.views) | |
207 gt.destroyview (gt, vlist[vid]); | |
208 remove (gt.gtid, dotty.graphs); | |
209 }; | |
210 dotty.protogt.loadgraph = function (gt, name, type, protograph, layoutflag) { | |
211 local fd, vid, vt, graph, nid, eid, gid; | |
212 | |
213 if (gt.layoutpending > 0) | |
214 gt.cancellayout (gt); | |
215 if (~name) | |
216 if (~(name = ask ('file name:', 'file', ''))) | |
217 return; | |
218 dotty.pushbusy (gt, gt.views); | |
219 dotty.message (1, 'loading'); | |
220 if (~protograph) | |
221 protograph = dotty.protogt.graph; | |
222 if ( | |
223 ~((fd = dotty.openio (name, type, 'r')) >= 0) | | |
224 ~(graph = readgraph (fd, protograph)) | |
225 ) { | |
226 dotty.message (0, 'cannot load graph'); | |
227 dotty.popbusy (gt, gt.views); | |
228 return; | |
229 } | |
230 for (vid in gt.views) { | |
231 vt = gt.views[vid]; | |
232 vt.colors = []; | |
233 vt.colorn = 2; | |
234 } | |
235 gt.graph = graph; | |
236 gt.name = name; | |
237 gt.type = type; | |
238 gt.undoarray = ['level' = 0; 'entries' = [];]; | |
239 if (~(type == 'file' & name == '-')) | |
240 closeio (fd); | |
241 graph.maxgid = tablesize (graph.graphs); | |
242 graph.maxnid = tablesize (graph.nodes); | |
243 graph.maxeid = tablesize (graph.edges); | |
244 for (nid in graph.nodes) | |
245 graph.nodes[nid][dotty.keys.nid] = nid; | |
246 for (eid in graph.edges) | |
247 graph.edges[eid][dotty.keys.eid] = eid; | |
248 for (gid in graph.graphs) | |
249 graph.graphs[gid][dotty.keys.gid] = gid; | |
250 gt.unpackattr (gt); | |
251 if (layoutflag) { | |
252 dotty.message (1, 'generating layout'); | |
253 gt.layoutgraph (gt); | |
254 } | |
255 dotty.popbusy (gt, gt.views); | |
256 return gt.graph; | |
257 }; | |
258 dotty.protogt.savegraph = function (gt, name, type) { | |
259 local fd; | |
260 | |
261 if (~name) | |
262 if (~(name = ask ('file name:', 'file', ''))) | |
263 return; | |
264 if ( | |
265 ~((fd = dotty.openio (name, type, 'w')) >= 0) | | |
266 ~writegraph (fd, gt.graph, 0) | |
267 ) { | |
268 dotty.message (0, 'cannot save graph'); | |
269 return; | |
270 } | |
271 if (~(type == 'file' & name == '-')) | |
272 closeio (fd); | |
273 }; | |
274 dotty.protogt.setgraph = function (gt, graph) { | |
275 local vid, vt, nid, eid, gid; | |
276 | |
277 if (gt.layoutpending > 0) | |
278 gt.cancellayout (gt); | |
279 for (vid in gt.views) { | |
280 vt = gt.views[vid]; | |
281 vt.colors = []; | |
282 vt.colorn = 2; | |
283 } | |
284 gt.graph = copy (graph); | |
285 gt.undoarray = ['level' = 0; 'entries' = [];]; | |
286 gt.unpackattr (gt); | |
287 gt.graph.maxgid = tablesize (graph.graphs); | |
288 gt.graph.maxnid = tablesize (graph.nodes); | |
289 gt.graph.maxeid = tablesize (graph.edges); | |
290 for (nid in gt.graph.nodes) | |
291 gt.graph.nodes[nid][dotty.keys.nid] = nid; | |
292 for (eid in gt.graph.edges) | |
293 gt.graph.edges[eid][dotty.keys.eid] = eid; | |
294 for (gid in gt.graph.graphs) | |
295 gt.graph.graphs[gid][dotty.keys.gid] = gid; | |
296 gt.unpackattr (gt); | |
297 dotty.message (1, 'generating layout'); | |
298 gt.layoutgraph (gt); | |
299 return gt.graph; | |
300 }; | |
301 dotty.protogt.erasegraph = function (gt, protogt, protovt) { | |
302 local vid, vt; | |
303 | |
304 if (gt.layoutpending > 0) | |
305 gt.cancellayout (gt); | |
306 for (vid in gt.views) { | |
307 vt = gt.views[vid]; | |
308 vt.colors = []; | |
309 vt.colorn = 2; | |
310 clear (vt.canvas); | |
311 } | |
312 if (~protogt) | |
313 protogt = dotty.protogt; | |
314 gt.graph = copy (protogt.graph); | |
315 gt.undoarray = ['level' = 0; 'entries' = [];]; | |
316 }; | |
317 dotty.protogt.layoutgraph = function (gt) { | |
318 if (gt.graph.graphattr.xdotversion) { | |
319 gt.unpacklayout (gt, gt.graph); | |
320 gt.setviewsize (gt.views, gt.graph.rect); | |
321 gt.redrawgraph (gt, gt.views); | |
322 return; | |
323 } | |
324 if (gt.layoutmode == 'async') { | |
325 if (~gt.haveinput) { | |
326 gt.startlayout (gt); | |
327 return; | |
328 } | |
329 if (~gt.finishlayout (gt)) | |
330 return; | |
331 gt.setviewsize (gt.views, gt.graph.rect); | |
332 gt.redrawgraph (gt, gt.views); | |
333 } else { | |
334 if (~gt.startlayout (gt)) | |
335 return; | |
336 else | |
337 while (~gt.finishlayout (gt)) | |
338 ; | |
339 gt.setviewsize (gt.views, gt.graph.rect); | |
340 gt.redrawgraph (gt, gt.views); | |
341 } | |
342 }; | |
343 dotty.protogt.createview = function (gt, protovt) { | |
344 local vt, ovt, id, t; | |
345 | |
346 vt = []; | |
347 vt.colors = []; | |
348 vt.colorn = 2; | |
349 if (~protovt) | |
350 protovt = dotty.protovt.normal; | |
351 if (protovt.mode ~= 'replace') { | |
352 for (id in dotty.protovt[protovt.type]) | |
353 vt[id] = copy (dotty.protovt[protovt.type][id]); | |
354 } | |
355 for (id in protovt) | |
356 vt[id] = copy (protovt[id]); | |
357 if (~(vt.parent >= 0)) { | |
358 vt.view = createwidget (-1, [ | |
359 'type' = 'view'; | |
360 'name' = vt.name; | |
361 'origin' = vt.orig; | |
362 'size' = vt.size; | |
363 ]); | |
364 vt.scroll = createwidget (vt.view, ['type' = 'scroll';]); | |
365 } else { | |
366 vt.view = -1; | |
367 vt.scroll = createwidget (vt.parent, [ | |
368 'type' = 'scroll'; | |
369 'size' = vt.size; | |
370 ]); | |
371 } | |
372 vt.canvas = createwidget (vt.scroll, [ | |
373 'type' = 'canvas'; | |
374 'color' = [0 = protovt.bgcolor; 1 = protovt.fgcolor;]; | |
375 ]); | |
376 setwidgetattr (vt.canvas, [ | |
377 'window' = vt.wrect; | |
378 'viewport' = vt.vsize; | |
379 ]); | |
380 clear (vt.canvas); | |
381 dotty.views[vt.canvas] = vt; | |
382 vt.vtid = vt.canvas; | |
383 vt.gtid = gt.gtid; | |
384 gt.views[vt.vtid] = vt; | |
385 dotty.views[vt.scroll] = vt; | |
386 if (vt.view ~= -1) | |
387 dotty.views[vt.view] = vt; | |
388 if (protovt.colors & tablesize (protovt.colors) > 0) { | |
389 for (id in protovt.colors) | |
390 if (id == '_bgcolor_') | |
391 setwidgetattr (vt.canvas, [ | |
392 'color' = [0 = protovt.colors[id];]; | |
393 ]); | |
394 else if (setwidgetattr (vt.canvas, ['color' = [ | |
395 protovt.colors[id] = id; | |
396 ];]) ~= 1) { | |
397 t = split (id, ' '); | |
398 if (tablesize (t) ~= 3 | setwidgetattr (vt.canvas, [ | |
399 'color' = [protovt.colors[id] = [ | |
400 'h' = ston (t[0]); 's' = ston (t[1]); 'v' = ston (t[2]); | |
401 ];]; | |
402 ]) ~= 1) { | |
403 dotty.message ( | |
404 0, concat ('unknown color ', id, ' using #1') | |
405 ); | |
406 } | |
407 } | |
408 vt.colors = copy (protovt.colors); | |
409 vt.colorn = protovt.colorn; | |
410 } else if (tablesize (gt.views) > 1) { | |
411 for (id in gt.views) | |
412 if (gt.views[id] ~= vt) | |
413 break; | |
414 ovt = gt.views[id]; | |
415 for (id in ovt.colors) | |
416 if (id == '_bgcolor_') | |
417 setwidgetattr (vt.canvas, ['color' = [0 = ovt.colors[id];];]); | |
418 else if (setwidgetattr (vt.canvas, ['color' = [ | |
419 ovt.colors[id] = id; | |
420 ];]) ~= 1) { | |
421 t = split (id, ' '); | |
422 if (tablesize (t) ~= 3 | setwidgetattr (vt.canvas, [ | |
423 'color' = [ovt.colors[id] = [ | |
424 'h' = ston (t[0]); 's' = ston (t[1]); 'v' = ston (t[2]); | |
425 ];]; | |
426 ]) ~= 1) { | |
427 dotty.message ( | |
428 0, concat ('unknown color ', id, ' using #1') | |
429 ); | |
430 } | |
431 } | |
432 vt.colors = copy (ovt.colors); | |
433 vt.colorn = ovt.colorn; | |
434 } | |
435 if (gt.graph.rect) | |
436 gt.setviewsize ([vt.vtid = vt;], gt.graph.rect); | |
437 gt.drawgraph (gt, [vt.vtid = vt;]); | |
438 for (id in vt.uifuncs) | |
439 if (id == 'closeview') | |
440 widgets[vt.view][id] = vt.uifuncs[id]; | |
441 else | |
442 widgets[vt.canvas][id] = vt.uifuncs[id]; | |
443 return vt; | |
444 }; | |
445 dotty.protogt.destroyview = function (gt, vt) { | |
446 destroywidget (vt.canvas); | |
447 destroywidget (vt.scroll); | |
448 if (vt.view ~= -1) { | |
449 destroywidget (vt.view); | |
450 remove (vt.view, dotty.views); | |
451 } | |
452 remove (vt.scroll, dotty.views); | |
453 remove (vt.canvas, dotty.views); | |
454 if (vt.gtid >= 0) | |
455 remove (vt.vtid, gt.views); | |
456 if (tablesize (dotty.views) == 0) | |
457 exit (); | |
458 }; | |
459 dotty.protogt.zoom = function (gt, vt, factor, pos) { | |
460 gt.setviewscale ([vt.vtid = vt;], factor); | |
461 if (pos) | |
462 gt.setviewcenter ([vt.vtid = vt;], pos); | |
463 gt.redrawgraph (gt, [vt.vtid = vt;]); | |
464 }; | |
465 dotty.protogt.findnode = function (gt, vt) { | |
466 local key, node, node1, nid; | |
467 | |
468 if (~(key = ask ('give node name or label'))) | |
469 return; | |
470 if (gt.graph.nodedict[key] >= 0) | |
471 node = gt.graph.nodes[gt.graph.nodedict[key]]; | |
472 else if (gt.graph.nodedict[ston (key)] >= 0) | |
473 node = gt.graph.nodes[gt.graph.nodedict[ston (key)]]; | |
474 else { | |
475 for (nid in gt.graph.nodes) { | |
476 node1 = gt.graph.nodes[nid]; | |
477 if (node1.attr.label == key | node1.attr.label == ston (key)) { | |
478 node = node1; | |
479 break; | |
480 } | |
481 } | |
482 } | |
483 if (~node) { | |
484 dotty.message (0, concat ('cannot find node: ', key)); | |
485 return; | |
486 } | |
487 gt.setviewcenter ([vt.vtid = vt;], node.pos); | |
488 }; | |
489 dotty.protogt.setattr = function (gt, obj) { | |
490 local kv, t, attr, value; | |
491 | |
492 if (~(kv = ask ('give attr/value, eg. color=blue'))) | |
493 return; | |
494 t = split (kv, '='); | |
495 attr = t[0]; | |
496 value = t[1]; | |
497 if ( | |
498 obj.attr == gt.graph.graphattr | | |
499 obj.attr == gt.graph.edgeattr | | |
500 obj.attr == gt.graph.nodeattr | |
501 ) { | |
502 obj.attr[attr] = value; | |
503 return; | |
504 } | |
505 if (obj.nid >= 0) { | |
506 gt.undrawnode (gt, gt.views, obj); | |
507 obj.attr[attr] = value; | |
508 gt.unpacknodeattr (gt, obj); | |
509 gt.drawnode (gt, gt.views, obj); | |
510 } else if (obj.eid >= 0) { | |
511 gt.undrawedge (gt, gt.views, obj); | |
512 obj.attr[attr] = value; | |
513 gt.unpackedgeattr (gt, obj); | |
514 gt.drawedge (gt, gt.views, obj); | |
515 } | |
516 }; | |
517 dotty.protogt.getattr = function (gt, node) { | |
518 local kv; | |
519 | |
520 if (~(kv.key = ask ('give attr name'))) | |
521 return null; | |
522 if ((kv.val = node.attr[kv.key])) | |
523 return kv; | |
524 return null; | |
525 }; | |
526 # | |
527 # utilities | |
528 # | |
529 dotty.createviewandgraph = function (name, type, protogt, protovt) { | |
530 local vt, gt; | |
531 | |
532 if (~protogt) | |
533 protogt = dotty.protogt; | |
534 if (protogt.creategraph) | |
535 gt = protogt.creategraph (protogt); | |
536 else | |
537 gt = dotty.protogt.creategraph (protogt); | |
538 vt = gt.createview (gt, protovt); | |
539 if (~protogt.graph) | |
540 protogt.graph = copy (dotty.protogt.graph); | |
541 if (name) | |
542 gt.loadgraph (gt, name, type, protogt.graph, 1); | |
543 return ['gt' = gt; 'vt' = vt;]; | |
544 }; | |
545 dotty.openio = function (name, type, mode) { | |
546 local fd; | |
547 | |
548 if (~name) | |
549 return null; | |
550 if (type == 'file') { | |
551 if (name == '-') { | |
552 if (mode == 'r' | mode == 'r+') | |
553 fd = 0; | |
554 else | |
555 fd = 1; | |
556 } else if (~((fd = openio ('file', name, mode)) >= 0)) { | |
557 dotty.message (0, concat ('cannot open file: ', name)); | |
558 return null; | |
559 } | |
560 } else if (type == 'pipe') { | |
561 if (~((fd = openio ( | |
562 'pipe', 'ksh', mode, concat ("%e ", name) | |
563 )) >= 0)) { | |
564 dotty.message (0, concat ('cannot run command: ', name)); | |
565 return null; | |
566 } | |
567 } else | |
568 return null; | |
569 return fd; | |
570 }; | |
571 dotty.pushbusy = function (gt, views) { | |
572 local vid; | |
573 | |
574 if (gt.busy == 0) | |
575 for (vid in gt.views) | |
576 setwidgetattr (vid, ['cursor' = 'watch';]); | |
577 gt.busy = gt.busy + 1; | |
578 }; | |
579 dotty.popbusy = function (gt, views) { | |
580 local vid; | |
581 | |
582 gt.busy = gt.busy - 1; | |
583 if (gt.busy == 0) | |
584 for (vid in gt.views) | |
585 setwidgetattr (vid, ['cursor' = 'default';]); | |
586 }; | |
587 dotty.message = function (level, text) { | |
588 if (level <= dotty.mlevel) | |
589 echo ('dotty.lefty: ', text); | |
590 }; | |
591 # | |
592 # printing or saving to file | |
593 # | |
594 dotty.protogt.printorsave = function (gt, vt, otype, name, mode, ptype) { | |
595 local pr, wrect, vsize, xy, psize, canvas, pscanvas, cid, cname, t; | |
596 local graph, edgehandles, fontmap, eid, edge, nid, node, gid, sgraph; | |
597 local did, draw, i; | |
598 | |
599 if (~otype) | |
600 if (~(otype = ask ('print to', 'choice', 'file|printer'))) | |
601 return; | |
602 if (otype == 'printer') { | |
603 if (~getenv ('TMPDIR')) | |
604 name = concat (getenv ('HOME'), '/.dottyout.ps'); | |
605 else | |
606 name = concat (getenv ('TMPDIR'), '/.dottyout.ps', random (10000)); | |
607 if (getenv ('LEFTYWINSYS') ~= 'mswin' & ~pr) | |
608 if (~(pr = ask ('printer command', 'string', 'lpr'))) | |
609 return; | |
610 } | |
611 if (~name) | |
612 if (~(name = ask ('postscript file', 'file', 'out.ps'))) | |
613 return; | |
614 if (~ptype) | |
615 if (~(ptype = ask ('page size', 'choice', '8.5x11|11x17|36x50'))) | |
616 return; | |
617 if (~mode) | |
618 if (~(mode = ask ('mode', 'choice', 'portrait|landscape|best fit'))) | |
619 return; | |
620 wrect = copy (vt.wrect); | |
621 wrect[0].x = wrect[0].x - 1; | |
622 wrect[1].x = wrect[1].x + 1; | |
623 wrect[0].y = wrect[0].y - 1; | |
624 wrect[1].y = wrect[1].y + 1; | |
625 vsize = copy (vt.vsize); | |
626 if (vsize.x == 0) | |
627 vsize.x = 1; | |
628 if (vsize.y == 0) | |
629 vsize.y = 1; | |
630 xy = vsize.x / vsize.y; | |
631 if (mode == 'best fit') { | |
632 if (xy < 1) | |
633 mode = 'portrait'; | |
634 else | |
635 mode = 'landscape'; | |
636 } | |
637 psize = dotty.pagesizes[ptype]; | |
638 if (mode == 'portrait') { | |
639 if (xy < psize.x / psize.y) { | |
640 vsize.y = psize.y * 300; | |
641 vsize.x = vsize.y * xy; | |
642 } else { | |
643 vsize.x = psize.x * 300; | |
644 vsize.y = vsize.x / xy; | |
645 } | |
646 } else { | |
647 if (xy < psize.y / psize.x) { | |
648 vsize.y = psize.x * 300; | |
649 vsize.x = vsize.y * xy; | |
650 } else { | |
651 vsize.x = psize.y * 300; | |
652 vsize.y = vsize.x / xy; | |
653 } | |
654 } | |
655 if (~((pscanvas = createwidget (-1, [ | |
656 'type' = 'ps'; | |
657 'origin' = ['x' = 0; 'y' = 0;]; | |
658 'size' = vsize; | |
659 'mode' = mode; | |
660 'name' = name; | |
661 ])) >= 0)) { | |
662 dotty.message (0, 'cannot open printer device'); | |
663 return; | |
664 } | |
665 for (cname in vt.colors) { | |
666 cid = vt.colors[cname]; | |
667 if (cname == '_bgcolor_') | |
668 setwidgetattr (pscanvas, ['color' = [0 = cid;];]); | |
669 else if (setwidgetattr (pscanvas, ['color' = [cid = cname;];]) ~= 1) { | |
670 t = split (cname, ' '); | |
671 if (tablesize (t) ~= 3 | setwidgetattr (pscanvas, [ | |
672 'color' = [cid = [ | |
673 'h' = ston (t[0]); 's' = ston (t[1]); 'v' = ston (t[2]); | |
674 ];]; | |
675 ]) ~= 1) { | |
676 dotty.message ( | |
677 0, concat ('unknown color ', cname, ' using #1') | |
678 ); | |
679 } | |
680 } | |
681 } | |
682 setwidgetattr (pscanvas, ['window' = wrect;]); | |
683 graph = copy (gt.graph); | |
684 canvas = vt.canvas; | |
685 vt.canvas = pscanvas; | |
686 edgehandles = gt.edgehandles; | |
687 gt.edgehandles = 0; | |
688 fontmap = dotty.maps[getenv ('LEFTYWINSYS')].psfontmap; | |
689 for (eid in graph.edges) { | |
690 edge = graph.edges[eid]; | |
691 edge.fontname = fontmap[edge.attr.fontname]; | |
692 for (did in edge.draws) { | |
693 if (did == 'ep') | |
694 continue; | |
695 draw = edge.draws[did]; | |
696 for (i = 0; draw[i]; i = i + 1) | |
697 if (draw[i].type == 'F') | |
698 draw[i].fn = fontmap[draw[i].ofn]; | |
699 } | |
700 gt.drawedge (gt, [0 = vt;], edge); | |
701 } | |
702 for (nid in graph.nodes) { | |
703 node = graph.nodes[nid]; | |
704 node.fontname = fontmap[node.attr.fontname]; | |
705 for (did in node.draws) { | |
706 if (did == 'ep') | |
707 continue; | |
708 draw = node.draws[did]; | |
709 for (i = 0; draw[i]; i = i + 1) | |
710 if (draw[i].type == 'F') | |
711 draw[i].fn = fontmap[draw[i].ofn]; | |
712 } | |
713 gt.drawnode (gt, [0 = vt;], node); | |
714 } | |
715 for (gid in graph.graphs) { | |
716 sgraph = graph.graphs[gid]; | |
717 sgraph.fontname = fontmap[sgraph.graphattr.fontname]; | |
718 for (did in sgraph.draws) { | |
719 if (did == 'ep') | |
720 continue; | |
721 draw = sgraph.draws[did]; | |
722 for (i = 0; draw[i]; i = i + 1) | |
723 if (draw[i].type == 'F') | |
724 draw[i].fn = fontmap[draw[i].ofn]; | |
725 } | |
726 gt.drawsgraph (gt, [0 = vt;], sgraph); | |
727 } | |
728 graph.fontname = fontmap[graph.graphattr.fontname]; | |
729 gt.drawsgraph (gt, [0 = vt;], graph); | |
730 gt.edgehandles = edgehandles; | |
731 vt.canvas = canvas; | |
732 destroywidget (pscanvas); | |
733 if (otype == 'printer' & getenv ('LEFTYWINSYS') ~= 'mswin') | |
734 system (concat (pr, ' ', name, '; rm ',name)); | |
735 }; |