Mercurial > hg > camir-aes2014
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/toolboxes/graph_visualisation/lib/lefty/dotty_layout.lefty Tue Feb 10 15:05:51 2015 +0000 @@ -0,0 +1,449 @@ +# +# dotty_layout: layout functions and data structures +# +dotty.grablserver = function (lserver) { + local fd; + + if (~dotty.lservers[lserver] | tablesize (dotty.lservers[lserver]) == 0) { + if (~((fd = openio ('pipe', lserver, 'r+', '%e -Txdot')) >= 0)) { + dotty.message (0, concat ('cannot start ', lserver)); + return null; + } + dotty.lservers[lserver][fd] = [ + 'fd' = fd; + 'count' = 0; + ]; + } + for (fd in dotty.lservers[lserver]) { + dotty.lservers[lserver][fd].count = dotty.lservers[ + lserver + ][fd].count + 1; + dotty.lservers.inuse[fd] = dotty.lservers[lserver][fd]; + remove (fd, dotty.lservers[lserver]); + return fd; + } +}; +dotty.releaselserver = function (lserver, fd, state) { + if (state == 'bad' | dotty.lservers.inuse[fd].count > 40) { + closeio (fd, 'kill'); + remove (fd, dotty.lservers.inuse); + return; + } + dotty.lservers[lserver][fd] = dotty.lservers.inuse[fd]; + remove (fd, dotty.lservers.inuse); +}; +dotty.protogt.startlayout = function (gt) { + local lpt, fd; + + if (gt.layoutpending >= 1) { + lpt = dotty.layoutpending[gt.gtid]; + if (gt.layoutmode == 'async') + monitor ('off', lpt.fd); + dotty.releaselserver (gt.lserver, lpt.fd, 'bad'); + remove (gt.gtid, dotty.layoutpending); + gt.layoutpending = 0; + gt.haveinput = 0; + dotty.popbusy (gt, gt.views); + } + if (~((fd = dotty.grablserver (gt.lserver)) >= 0)) + return null; + dotty.pushbusy (gt, gt.views); + writegraph (fd, gt.graph, 1); + gt.layoutpending = 1; + dotty.layoutpending[gt.gtid] = [ + 'fd' = fd; + 'gtid' = gt.gtid; + ]; + if (gt.layoutmode == 'async') + monitor ('on', fd); + return 1; +}; +dotty.protogt.finishlayout = function (gt) { + local graph, lpt, fd; + + if (~(gt.layoutpending >= 1)) { + dotty.message (0, concat ('no layout pending for graph ', gt.gtid)); + return null; + } + lpt = dotty.layoutpending[gt.gtid]; + if (~(graph = readgraph (lpt.fd))) { + if (gt.layoutmode == 'async') + monitor ('off', lpt.fd); + dotty.releaselserver (gt.lserver, lpt.fd, 'bad'); + if (gt.layoutpending == 2) { + dotty.message (0, concat ('giving up on ', gt.lserver)); + if ((fd = openio ('file', 'dottybug.dot', 'w+')) >= 0) { + writegraph (fd, gt.graph, 0); + closeio (fd); + dotty.message ( + 0, concat ('graph that causes ', gt.lserver) + ); + dotty.message ( + 0, 'to fail has been saved in file dottybug.dot' + ); + dotty.message ( + 0, 'please fill out a bug report at' + ); + dotty.message ( + 0, 'http://www.graphviz.org/bugs/bugform.html' + ); + } + dotty.popbusy (gt, gt.views); + gt.layoutpending = 0; + gt.haveinput = 0; + return 1; + } + dotty.message ( + 1, concat ('lost connection to ', gt.lserver, ', restarting...') + ); + lpt.fd = dotty.grablserver (gt.lserver); + writegraph (lpt.fd, gt.graph, 1); + if (gt.layoutmode == 'async') + monitor ('on', lpt.fd); + gt.layoutpending = 2; + gt.haveinput = 0; + return null; + } + if (gt.layoutmode == 'async') + monitor ('off', lpt.fd); + dotty.releaselserver (gt.lserver, lpt.fd, null); + remove (gt.gtid, dotty.layoutpending); + gt.layoutpending = 0; + gt.haveinput = 0; + gt.unpacklayout (gt, graph); + dotty.popbusy (gt, gt.views); + return 1; +}; +dotty.protogt.cancellayout = function (gt) { + local lpt, vid; + + if (gt.layoutpending >= 1) { + lpt = dotty.layoutpending[gt.gtid]; + if (gt.layoutmode == 'async') + monitor ('off', lpt.fd); + dotty.releaselserver (gt.lserver, lpt.fd, 'bad'); + remove (gt.gtid, dotty.layoutpending); + gt.layoutpending = 0; + gt.haveinput = 0; + dotty.popbusy (gt, gt.views); + } +}; +dotty.protogt.unpacklayout = function (gt, graph2) { + local graph, gid, sgraph1, sgraph2, nid, node1, node2, eid, edge1, edge2; + local t1, pos, size; + + graph = gt.graph; + for (gid in graph2.graphdict) { + if (~(sgraph1 = graph.graphs[graph.graphdict[gid]])) + continue; + sgraph2 = graph2.graphs[graph2.graphdict[gid]]; + sgraph1.draws = gt.unpackalldraw (gt, sgraph2.graphattr); + } + for (nid in graph2.nodedict) { + if (~(node1 = graph.nodes[graph.nodedict[nid]])) + continue; + node2 = graph2.nodes[graph2.nodedict[nid]]; + node1.draws = gt.unpackalldraw (gt, node2.attr); + t1 = split (node2.attr.pos, ','); + pos = ['x' = ston (t1[0]); 'y' = ston (t1[1]);]; + size = [ + 'x' = ston (node2.attr.width) * 72; + 'y' = ston (node2.attr.height) * 72; + ]; + node1.pos = pos; + node1.size = size; + node1.rect = [ + 0 = ['x' = pos.x - size.x / 2; 'y' = pos.y - size.y / 2;]; + 1 = ['x' = pos.x + size.x / 2; 'y' = pos.y + size.y / 2;]; + ]; + } + for (eid in graph2.edges) { + edge2 = graph2.edges[eid]; + if (edge2.attr.id) { + if (~(edge1 = graph.edges[ston (edge2.attr.id)])) + continue; + } else if (graph == graph2) + edge1 = edge2; + edge1.draws = gt.unpackalldraw (gt, edge2.attr); + } + graph.draws = gt.unpackalldraw (gt, graph2.graphattr); + t1 = split (graph2.graphattr.bb, ','); + graph.rect[0].x = ston (t1[0]); + graph.rect[0].y = ston (t1[1]); + graph.rect[1].x = ston (t1[2]); + graph.rect[1].y = ston (t1[3]); + if (gt.graph ~= graph2) + return; + # strip position and size info from the attributes + for (gid in graph2.graphdict) { + sgraph2 = graph2.graphs[graph2.graphdict[gid]]; + gt.removealldraw (gt, sgraph2.graphattr); + if (sgraph2.graphattr.bb) + remove ('bb', sgraph2.graphattr); + } + for (nid in graph2.nodedict) { + node2 = graph2.nodes[graph2.nodedict[nid]]; + gt.removealldraw (gt, node2.attr); + if (node2.attr.rects) + remove ('rects', node2.attr); + remove ('pos', node2.attr); + remove ('width', node2.attr); + remove ('height', node2.attr); + } + for (eid in graph2.edges) { + edge2 = graph2.edges[eid]; + gt.removealldraw (gt, edge2.attr); + if (edge2.attr.pos) + remove ('pos', edge2.attr); + if (edge2.attr.lp) + remove ('lp', edge2.attr); + } + gt.removealldraw (gt, graph2.graphattr); + remove ('bb', graph2.graphattr); + if (graph2.graphattr.lp) + remove ('lp', graph2.graphattr); +}; +# +# draw directive parsing +# +dotty.protogt.unpackalldraw = function (gt, attr) { + local o, did; + + o = []; + if (attr._draw_) + o._draw_ = gt.unpackdraw (gt, attr._draw_); + if (attr._ldraw_) + o._ldraw_ = gt.unpackdraw (gt, attr._ldraw_); + if (attr._hdraw_) + o._hdraw_ = gt.unpackdraw (gt, attr._hdraw_); + if (attr._tdraw_) + o._tdraw_ = gt.unpackdraw (gt, attr._tdraw_); + if (attr._hldraw_) + o._hldraw_ = gt.unpackdraw (gt, attr._hldraw_); + if (attr._tldraw_) + o._tldraw_ = gt.unpackdraw (gt, attr._tldraw_); + for (did in o) + if (o[did].ep) { + o.ep = o[did].ep; + break; + } + return o; +}; +dotty.protogt.removealldraw = function (gt, attr) { + if (attr._draw_) + remove ('_draw_', attr); + if (attr._ldraw_) + remove ('_ldraw_', attr); + if (attr._hdraw_) + remove ('_hdraw_', attr); + if (attr._tdraw_) + remove ('_tdraw_', attr); + if (attr._hldraw_) + remove ('_hldraw_', attr); + if (attr._tldraw_) + remove ('_tldraw_', attr); +}; +dotty.protogt.unpackdraw = function (gt, attr) { + local oo, o, tt, t, n, i, j, s, l, ep; + + oo = []; + t = split (attr, ' ', 0); + n = tablesize (t); + if (t[n - 1] == '') { + remove (n - 1, t); + n = n - 1; + } + i = 0; + while (i < n) { + o = []; + if (t[i] == 'E') { + o.type = t[i]; + o.c.x = ston (t[i + 1]); + o.c.y = ston (t[i + 2]); + o.s.x = ston (t[i + 3]); + o.s.y = ston (t[i + 4]); + i = i + 5; + } else if (t[i] == 'e') { + o.type = t[i]; + o.c.x = ston (t[i + 1]); + o.c.y = ston (t[i + 2]); + o.s.x = ston (t[i + 3]); + o.s.y = ston (t[i + 4]); + i = i + 5; + } else if (t[i] == 'P') { + o.type = t[i]; + o.n = ston (t[i + 1]); + for (j = 0; j < o.n; j = j + 1) { + o.ps[j].x = ston (t[i + 2 + j * 2]); + o.ps[j].y = ston (t[i + 2 + j * 2 + 1]); + } + i = i + 2 + o.n * 2; + o.ps[o.n] = o.ps[0]; + o.n = o.n + 1; + } else if (t[i] == 'p') { + o.type = t[i]; + o.n = ston (t[i + 1]); + for (j = 0; j < o.n; j = j + 1) { + o.ps[j].x = ston (t[i + 2 + j * 2]); + o.ps[j].y = ston (t[i + 2 + j * 2 + 1]); + } + i = i + 2 + o.n * 2; + o.ps[o.n] = o.ps[0]; + o.n = o.n + 1; + } else if (t[i] == 'L') { + o.type = t[i]; + o.n = ston (t[i + 1]); + for (j = 0; j < o.n; j = j + 1) { + o.ps[j].x = ston (t[i + 2 + j * 2]); + o.ps[j].y = ston (t[i + 2 + j * 2 + 1]); + } + i = i + 2 + o.n * 2; + if (~ep) + ep = copy (o.ps[1]); + } else if (t[i] == 'B') { + o.type = t[i]; + o.n = ston (t[i + 1]); + for (j = 0; j < o.n; j = j + 1) { + o.ps[j].x = ston (t[i + 2 + j * 2]); + o.ps[j].y = ston (t[i + 2 + j * 2 + 1]); + } + i = i + 2 + o.n * 2; + if (~ep) + ep = copy (o.ps[1]); + } else if (t[i] == 'b') { + o.type = t[i]; + o.n = ston (t[i + 1]); + for (j = 0; j < o.n; j = j + 1) { + o.ps[j].x = ston (t[i + 2 + j * 2]); + o.ps[j].y = ston (t[i + 2 + j * 2 + 1]); + } + i = i + 2 + o.n * 2; + if (~ep) + ep = copy (o.ps[1]); + } else if (t[i] == 'T') { + o.type = t[i]; + o.p.x = ston (t[i + 1]); + o.p.y = ston (t[i + 2]); + o.j = ston (t[i + 3]); + if (o.j == -1) + o.j = 'lb'; + else if (o.j == 1) + o.j = 'rb'; + else if (o.j == 0) + o.j = 'cb'; + o.w = ston (t[i + 4]); + o.n = ston (t[i + 5]); + i = i + 6; + s = t[i]; + i = i + 1; + l = strlen (s) - 1; + while (l < o.n) { + s = concat (s, ' ', t[i]); + l = l + 1 + strlen (t[i]); + i = i + 1; + } + tt = split (s, ''); + l = tablesize (tt); + s = ''; + for (j = 1; j < l; j = j + 1) + s = concat (s, tt[j]); + o.s = s; + } else if (t[i] == 'C') { + o.type = t[i]; + o.n = ston (t[i + 1]); + i = i + 2; + s = t[i]; + i = i + 1; + l = strlen (s) - 1; + while (l < o.n) { + s = concat (s, ' ', t[i]); + l = l + 1 + strlen (t[i]); + i = i + 1; + } + tt = split (s, ''); + l = tablesize (tt); + s = ''; + for (j = 1; j < l; j = j + 1) + s = concat (s, tt[j]); + o.fillcolor = gt.getcolor (gt.views, s); + } else if (t[i] == 'c') { + o.type = t[i]; + o.n = ston (t[i + 1]); + i = i + 2; + s = t[i]; + i = i + 1; + l = strlen (s) - 1; + while (l < o.n) { + s = concat (s, ' ', t[i]); + l = l + 1 + strlen (t[i]); + i = i + 1; + } + tt = split (s, ''); + l = tablesize (tt); + s = ''; + for (j = 1; j < l; j = j + 1) + s = concat (s, tt[j]); + o.drawcolor = gt.getcolor (gt.views, s); + } else if (t[i] == 'F') { + o.type = t[i]; + o.fs = ston (t[i + 1]); + o.n = ston (t[i + 2]); + i = i + 3; + s = t[i]; + i = i + 1; + l = strlen (s) - 1; + while (l < o.n) { + s = concat (s, ' ', t[i]); + l = l + 1 + strlen (t[i]); + i = i + 1; + } + tt = split (s, ''); + l = tablesize (tt); + s = ''; + for (j = 1; j < l; j = j + 1) + s = concat (s, tt[j]); + o.ofn = s; + o.fn = dotty.fontmap[s]; + } else if (t[i] == 'S') { + o.type = t[i]; + o.n = ston (t[i + 1]); + i = i + 2; + s = t[i]; + i = i + 1; + l = strlen (s) - 1; + while (l < o.n) { + s = concat (s, ' ', t[i]); + l = l + 1 + strlen (t[i]); + i = i + 1; + } + tt = split (s, ''); + l = tablesize (tt); + s = ''; + for (j = 1; j < l; j = j + 1) + s = concat (s, tt[j]); + if ( + s == 'solid' | s == 'dashed' | s == 'dotted' | + s == 'longdashed' | s == 'shortdashed' + ) + o.style = s; + else if (s == 'bold') + o.width = 3; + else { + tt = split (s, '('); + if (tt[0] == 'setlinewidth') { + tt = split (tt[1], ')'); + o.width = ston (tt[0]); + } else + continue; + } + } else if (t[i] == 'I') { + i = i + 7; + } else { + dotty.message (0, concat ('draw language parser error: ', t[i])); + return null; + } + oo[tablesize (oo)] = o; + } + oo.ep = ep; + return oo; +};