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;
+};