annotate toolboxes/graph_visualisation/lib/lefty/dotty.lefty @ 0:cc4b1211e677 tip

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