wolffd@0: # wolffd@0: # dotty_ui: user interface functions and data structures wolffd@0: # wolffd@0: dotty.protogt.doaction = function (data, s) { wolffd@0: local vt, gt; wolffd@0: wolffd@0: vt = dotty.views[data.widget]; wolffd@0: gt = dotty.graphs[vt.gtid]; wolffd@0: data.menuitem = s; wolffd@0: if (data.obj.nid >= 0) { wolffd@0: if (gt.actions.node[s]) { wolffd@0: gt.actions.node[s] (gt, vt, data.obj, data); wolffd@0: return; wolffd@0: } wolffd@0: } else if (data.obj.eid >= 0) { wolffd@0: if (gt.actions.edge[s]) { wolffd@0: gt.actions.edge[s] (gt, vt, data.obj, data); wolffd@0: return; wolffd@0: } wolffd@0: } wolffd@0: if (gt.actions.general[s]) wolffd@0: gt.actions.general[s] (gt, vt, data); wolffd@0: }; wolffd@0: dotty.protogt.actions.general = [ wolffd@0: "undo" = function (gt, vt, data) { wolffd@0: gt.undo (gt, 1); wolffd@0: }; wolffd@0: "paste" = function (gt, vt, data) { wolffd@0: gt.paste (gt, data.pos, 1); wolffd@0: }; wolffd@0: "do layout" = function (gt, vt, data) { wolffd@0: gt.layoutgraph (gt); wolffd@0: }; wolffd@0: "cancel layout" = function (gt, vt, data) { wolffd@0: gt.cancellayout (gt); wolffd@0: }; wolffd@0: "redraw" = function (gt, vt, data) { wolffd@0: gt.redrawgraph (gt, [vt.vtid = vt;]); wolffd@0: }; wolffd@0: "new graph" = function (gt, vt, data) { wolffd@0: gt.erasegraph (gt, null, null); wolffd@0: }; wolffd@0: "load graph" = function (gt, vt, data) { wolffd@0: gt.loadgraph (gt, null, 'file', dotty.protogt.graph, 1); wolffd@0: }; wolffd@0: "reload graph" = function (gt, vt, data) { wolffd@0: gt.loadgraph (gt, gt.name, gt.type, gt.graph, 1); wolffd@0: }; wolffd@0: "save graph" = function (gt, vt, data) { wolffd@0: gt.savegraph (gt, gt.name, gt.type); wolffd@0: }; wolffd@0: "save graph as" = function (gt, vt, data) { wolffd@0: gt.savegraph (gt, null, 'file'); wolffd@0: }; wolffd@0: "open view" = function (gt, vt, data) { wolffd@0: gt = dotty.protogt.creategraph (null); wolffd@0: gt.createview (gt, null); wolffd@0: }; wolffd@0: "copy view" = function (gt, vt, data) { wolffd@0: gt = gt.copygraph (gt); wolffd@0: gt.createview (gt, vt); wolffd@0: }; wolffd@0: "birdseye view" = function (gt, vt, data) { wolffd@0: gt.createview (gt, dotty.protovt.birdseye); wolffd@0: }; wolffd@0: "clone view" = function (gt, vt, data) { wolffd@0: gt.createview (gt, vt); wolffd@0: }; wolffd@0: "close view" = function (gt, vt, data) { wolffd@0: gt.destroyview (gt, vt); wolffd@0: if (tablesize (gt.views) == 0) wolffd@0: gt.destroygraph (gt); wolffd@0: }; wolffd@0: "set graph attr" = function (gt, vt, data) { wolffd@0: gt.setattr (gt, ['attr' = gt.graph.graphattr;]); wolffd@0: }; wolffd@0: "set node attr" = function (gt, vt, data) { wolffd@0: gt.setattr (gt, ['attr' = gt.graph.nodeattr;]); wolffd@0: }; wolffd@0: "set edge attr" = function (gt, vt, data) { wolffd@0: gt.setattr (gt, ['attr' = gt.graph.edgeattr;]); wolffd@0: }; wolffd@0: "zoom in" = function (gt, vt, data) { wolffd@0: gt.zoom (gt, vt, 0.5, data.pos); wolffd@0: }; wolffd@0: "zoom out" = function (gt, vt, data) { wolffd@0: gt.zoom (gt, vt, 2, data.pos); wolffd@0: }; wolffd@0: "zoom in slowly" = function (gt, vt, data) { wolffd@0: gt.zoom (gt, vt, 0.9, data.pos); wolffd@0: }; wolffd@0: "zoom out slowly" = function (gt, vt, data) { wolffd@0: gt.zoom (gt, vt, 1.1, data.pos); wolffd@0: }; wolffd@0: "scroll horizontally" = function (gt, vt, data) { wolffd@0: vt.scrollmode = 'h'; wolffd@0: }; wolffd@0: "scroll vertically" = function (gt, vt, data) { wolffd@0: vt.scrollmode = 'v'; wolffd@0: }; wolffd@0: "find node" = function (gt, vt, data) { wolffd@0: gt.findnode (gt, vt); wolffd@0: }; wolffd@0: "print graph" = function (gt, vt, data) { wolffd@0: gt.printorsave (gt, vt, null, null, null, null); wolffd@0: }; wolffd@0: "text view" = function (gt, vt, data) { wolffd@0: if (dotty.txtview == 'on') wolffd@0: dotty.txtview = 'off'; wolffd@0: else wolffd@0: dotty.txtview = 'on'; wolffd@0: txtview (dotty.txtview); wolffd@0: }; wolffd@0: "quit" = function (gt, vt, data) { wolffd@0: exit (); wolffd@0: }; wolffd@0: ]; wolffd@0: dotty.protogt.actions.node = [ wolffd@0: "cut" = function (gt, vt, obj, data) { wolffd@0: gt.cut (gt, obj, 'one', 'support', 'cut'); wolffd@0: dotty.clipgt.layoutgraph (dotty.clipgt); wolffd@0: }; wolffd@0: "Cut" = function (gt, vt, obj, data) { wolffd@0: gt.cut (gt, obj, 'reachable', 'support', 'cut'); wolffd@0: dotty.clipgt.layoutgraph (dotty.clipgt); wolffd@0: }; wolffd@0: "copy" = function (gt, vt, obj, data) { wolffd@0: gt.cut (gt, obj, 'one', 'support', 'copy'); wolffd@0: dotty.clipgt.layoutgraph (dotty.clipgt); wolffd@0: }; wolffd@0: "Copy" = function (gt, vt, obj, data) { wolffd@0: gt.cut (gt, obj, 'reachable', 'support', 'copy'); wolffd@0: dotty.clipgt.layoutgraph (dotty.clipgt); wolffd@0: }; wolffd@0: "group" = function (gt, vt, obj, data) { wolffd@0: local kv; wolffd@0: wolffd@0: if ((kv = gt.getattr (gt, obj))) wolffd@0: gt.groupnodesbyattr (gt, kv.key, kv.val, [ wolffd@0: 'label' = kv.val; kv.key = kv.val; wolffd@0: ], 1, 1); wolffd@0: }; wolffd@0: "Group" = function (gt, vt, obj, data) { wolffd@0: local kv; wolffd@0: wolffd@0: if ((kv = gt.getattr (gt, obj))) wolffd@0: gt.groupnodesbyattr (gt, kv.key, kv.val, [ wolffd@0: 'label' = kv.val; kv.key = kv.val; wolffd@0: ], 0, 1); wolffd@0: }; wolffd@0: "delete" = function (gt, vt, obj, data) { wolffd@0: if (obj.eid >= 0) wolffd@0: gt.removeedge (gt, obj); wolffd@0: else wolffd@0: gt.removenode (gt, obj); wolffd@0: }; wolffd@0: "Delete" = function (gt, vt, obj, data) { wolffd@0: gt.removesubtree (gt, obj); wolffd@0: }; wolffd@0: "remove" = function (gt, vt, obj, data) { wolffd@0: if (obj.nid >= 0) wolffd@0: if ((kv = gt.getattr (gt, obj))) wolffd@0: gt.removenodesbyattr (gt, kv.key, kv.val); wolffd@0: }; wolffd@0: "Remove" = function (gt, vt, obj, data) { wolffd@0: if (obj.nid >= 0) wolffd@0: if ((kv = gt.getattr (gt, obj))) wolffd@0: gt.removesubtreesbyattr (gt, kv.key, kv.val); wolffd@0: }; wolffd@0: "set attr" = function (gt, vt, obj, data) { wolffd@0: gt.setattr (gt, obj); wolffd@0: }; wolffd@0: "print attr" = function (gt, vt, obj, data) { wolffd@0: if (obj.nid >= 0) wolffd@0: echo ('node: ', obj.name); wolffd@0: dump (obj.attr); wolffd@0: }; wolffd@0: ]; wolffd@0: dotty.protogt.actions.edge = dotty.protogt.actions.node; wolffd@0: dotty.protovt.normal.menus = [ wolffd@0: 'general' = [ wolffd@0: 0 = "undo"; wolffd@0: 1 = "paste"; wolffd@0: 2 = "do layout"; wolffd@0: 3 = "cancel layout"; wolffd@0: 4 = "redraw"; wolffd@0: 5 = "new graph"; wolffd@0: 6 = "load graph"; wolffd@0: 7 = "reload graph"; wolffd@0: 8 = "save graph"; wolffd@0: 9 = "save graph as"; wolffd@0: 10 = "open view"; wolffd@0: 11 = "copy view"; wolffd@0: 12 = "clone view"; wolffd@0: 13 = "birdseye view"; wolffd@0: 14 = "close view"; wolffd@0: 15 = "set graph attr"; wolffd@0: 16 = "set node attr"; wolffd@0: 17 = "set edge attr"; wolffd@0: 18 = "zoom in"; wolffd@0: 19 = "zoom out"; wolffd@0: 20 = "find node"; wolffd@0: 21 = "print graph"; wolffd@0: 22 = "text view"; wolffd@0: 23 = "quit"; wolffd@0: ]; wolffd@0: 'node' = [ wolffd@0: 0 = "cut"; wolffd@0: 1 = "Cut"; wolffd@0: 2 = "copy"; wolffd@0: 3 = "Copy"; wolffd@0: 4 = "group"; wolffd@0: 5 = "Group"; wolffd@0: 6 = "delete"; wolffd@0: 7 = "Delete"; wolffd@0: 8 = "remove"; wolffd@0: 9 = "Remove"; wolffd@0: 10 = "set attr"; wolffd@0: 11 = "print attr"; wolffd@0: ]; wolffd@0: 'edge' = [ wolffd@0: 0 = "cut"; wolffd@0: 1 = "Cut"; wolffd@0: 2 = "copy"; wolffd@0: 3 = "Copy"; wolffd@0: 4 = "delete"; wolffd@0: 5 = "Delete"; wolffd@0: 6 = "set attr"; wolffd@0: 7 = "print attr"; wolffd@0: ]; wolffd@0: ]; wolffd@0: dotty.protovt.normal.keys = [ wolffd@0: 'general' = [ wolffd@0: 'u' = "undo"; wolffd@0: 'p' = "paste"; wolffd@0: 'l' = "do layout"; wolffd@0: 'k' = "cancel layout"; wolffd@0: ' ' = "redraw"; wolffd@0: 'L' = "reload graph"; wolffd@0: 's' = "save graph"; wolffd@0: 'Z' = "zoom in slowly"; wolffd@0: 'z' = "zoom out slowly"; wolffd@0: 'h' = "scroll horizontally"; wolffd@0: 'v' = "scroll vertically"; wolffd@0: ]; wolffd@0: 'node' = [ wolffd@0: 'c' = "copy"; wolffd@0: 'C' = "Copy"; wolffd@0: 'g' = "group"; wolffd@0: 'G' = "Group"; wolffd@0: 'd' = "delete"; wolffd@0: 'D' = "Delete"; wolffd@0: 'r' = "remove"; wolffd@0: 'R' = "Remove"; wolffd@0: 'a' = "set attr"; wolffd@0: ]; wolffd@0: 'edge' = [ wolffd@0: 'c' = "copy"; wolffd@0: 'C' = "Copy"; wolffd@0: 'd' = "delete"; wolffd@0: 'D' = "Delete"; wolffd@0: 'a' = "set attr"; wolffd@0: ]; wolffd@0: ]; wolffd@0: dotty.protovt.birdseye.menus = dotty.protovt.normal.menus; wolffd@0: dotty.protovt.birdseye.keys = dotty.protovt.normal.keys; wolffd@0: dotty.protovt.normal.uifuncs = [ wolffd@0: 'leftdown' = function (data) { wolffd@0: local gt; wolffd@0: wolffd@0: gt = dotty.graphs[dotty.views[data.widget].gtid]; wolffd@0: if (data.obj.nid >= 0) { wolffd@0: dotty.node2move = data.obj; wolffd@0: dotty.movewidget = data.widget; wolffd@0: dotty.rp2 = data.pos; wolffd@0: } wolffd@0: }; wolffd@0: 'leftmove' = function (data) { wolffd@0: local gt; wolffd@0: wolffd@0: gt = dotty.graphs[dotty.views[data.widget].gtid]; wolffd@0: if (dotty.node2move & ( wolffd@0: dotty.rp2.x ~= data.pos.x | dotty.rp2.y ~= data.pos.y wolffd@0: )) { wolffd@0: gt.movenode (gt, dotty.node2move, data.pos); wolffd@0: dotty.rp2 = data.pos; wolffd@0: } wolffd@0: }; wolffd@0: 'leftup' = function (data) { wolffd@0: local gt; wolffd@0: wolffd@0: gt = dotty.graphs[dotty.views[data.widget].gtid]; wolffd@0: if (dotty.node2move) { wolffd@0: if (dotty.movewidget == data.widget) wolffd@0: gt.movenode (gt, dotty.node2move, data.pos); wolffd@0: dotty.node2move = 0; wolffd@0: } else if (~data.obj) wolffd@0: gt.insertnode (gt, data.pos, null, null, null, 1); wolffd@0: }; wolffd@0: 'middledown' = function (data) { wolffd@0: if (~(data.obj.nid >= 0)) wolffd@0: return; wolffd@0: dotty.rubberband = 1; wolffd@0: dotty.movewidget = data.widget; wolffd@0: setgfxattr (data.widget, ['mode' = 'xor';]); wolffd@0: dotty.rp1 = data.pos; wolffd@0: dotty.rp2 = data.pos; wolffd@0: line (data.widget, null, dotty.rp1, dotty.rp2, ['color' = 1;]); wolffd@0: }; wolffd@0: 'middlemove' = function (data) { wolffd@0: if (dotty.rubberband ~= 1 | ( wolffd@0: dotty.rp2.x == data.pos.x & dotty.rp2.y == data.pos.y wolffd@0: )) wolffd@0: return; wolffd@0: line (data.widget, null, dotty.rp1, dotty.rp2, ['color' = 1;]); wolffd@0: dotty.rp2 = data.pos; wolffd@0: line (data.widget, null, dotty.rp1, dotty.rp2, ['color' = 1;]); wolffd@0: }; wolffd@0: 'middleup' = function (data) { wolffd@0: local gt; wolffd@0: wolffd@0: gt = dotty.graphs[dotty.views[data.widget].gtid]; wolffd@0: if (dotty.rubberband ~= 1) wolffd@0: return; wolffd@0: dotty.rubberband = 0; wolffd@0: line (dotty.movewidget, null, dotty.rp1, dotty.rp2, ['color' = 1;]); wolffd@0: setgfxattr (dotty.movewidget, ['mode' = 'src';]); wolffd@0: if (dotty.movewidget ~= data.widget | ~( wolffd@0: data.pobj.nid >= 0) | ~(data.obj.nid >= 0 wolffd@0: )) wolffd@0: return; wolffd@0: if (data.pobj.attr.support) wolffd@0: gt.groupnodes (gt, [ wolffd@0: data.obj.nid = data.obj; wolffd@0: data.pobj.nid = data.pobj; wolffd@0: ], data.obj, null, null, null, 1, 1); wolffd@0: else if (data.obj.attr.support) wolffd@0: gt.groupnodes (gt, [ wolffd@0: data.obj.nid = data.obj; wolffd@0: data.pobj.nid = data.pobj; wolffd@0: ], data.pobj, null, null, null, 1, 1); wolffd@0: else wolffd@0: gt.insertedge (gt, data.pobj, null, data.obj, null, null, 1); wolffd@0: }; wolffd@0: 'rightdown' = function (data) { wolffd@0: local vt, gt, menu, i; wolffd@0: wolffd@0: vt = dotty.views[data.widget]; wolffd@0: gt = dotty.graphs[vt.gtid]; wolffd@0: if (~data.obj) wolffd@0: menu = vt.menus.general; wolffd@0: else if (data.obj.nid >= 0) wolffd@0: menu = vt.menus.node; wolffd@0: else if (data.obj.eid >= 0) wolffd@0: menu = vt.menus.edge; wolffd@0: if ((i = displaymenu (data.widget, menu)) >= 0) wolffd@0: gt.doaction (data, menu[i]); wolffd@0: }; wolffd@0: 'button3up' = function (data) { wolffd@0: local vt, attr; wolffd@0: wolffd@0: vt = dotty.views[data.widget]; wolffd@0: attr = getwidgetattr (vt.scroll, [0 = 'childcenter';]); wolffd@0: if (vt.scrollmode == 'h') wolffd@0: attr.childcenter.x = attr.childcenter.x - 40; wolffd@0: else wolffd@0: attr.childcenter.y = attr.childcenter.y - 40; wolffd@0: setwidgetattr (vt.scroll, ['childcenter' = attr.childcenter;]); wolffd@0: }; wolffd@0: 'button4up' = function (data) { wolffd@0: local vt, attr; wolffd@0: wolffd@0: vt = dotty.views[data.widget]; wolffd@0: attr = getwidgetattr (vt.scroll, [0 = 'childcenter';]); wolffd@0: if (vt.scrollmode == 'h') wolffd@0: attr.childcenter.x = attr.childcenter.x + 40; wolffd@0: else wolffd@0: attr.childcenter.y = attr.childcenter.y + 40; wolffd@0: setwidgetattr (vt.scroll, ['childcenter' = attr.childcenter;]); wolffd@0: }; wolffd@0: 'keyup' = function (data) { wolffd@0: local vt, gt, action; wolffd@0: wolffd@0: vt = dotty.views[data.widget]; wolffd@0: gt = dotty.graphs[vt.gtid]; wolffd@0: if (data.obj.nid >= 0) { wolffd@0: if (vt.keys.node[data.key]) wolffd@0: action = vt.keys.node[data.key]; wolffd@0: } else if (data.obj.eid >= 0) { wolffd@0: if (vt.keys.edge[data.key]) wolffd@0: action = vt.keys.edge[data.key]; wolffd@0: } wolffd@0: if (~action) wolffd@0: if (vt.keys.general[data.key]) wolffd@0: action = vt.keys.general[data.key]; wolffd@0: if (action) wolffd@0: gt.doaction (data, action); wolffd@0: }; wolffd@0: 'redraw' = function (data) { wolffd@0: local vt, gt; wolffd@0: wolffd@0: vt = dotty.views[data.widget]; wolffd@0: gt = dotty.graphs[vt.gtid]; wolffd@0: gt.drawgraph (gt, [vt.vtid = vt;]); wolffd@0: }; wolffd@0: 'closeview' = function (data) { wolffd@0: local vt, gt; wolffd@0: wolffd@0: vt = dotty.views[data.widget]; wolffd@0: gt = dotty.graphs[vt.gtid]; wolffd@0: gt.destroyview (gt, vt); wolffd@0: if (tablesize (gt.views) == 0) wolffd@0: gt.destroygraph (gt); wolffd@0: }; wolffd@0: ]; wolffd@0: dotty.protovt.birdseye.uifuncs = [ wolffd@0: 'leftdown' = function (data) { wolffd@0: local gt, vid; wolffd@0: wolffd@0: gt = dotty.graphs[dotty.views[data.widget].gtid]; wolffd@0: for (vid in gt.views) { wolffd@0: vt = gt.views[vid]; wolffd@0: if (vt.type ~= 'birdseye') wolffd@0: gt.setviewcenter ([vid = vt;], data.pos); wolffd@0: } wolffd@0: }; wolffd@0: 'leftmove' = function (data) { wolffd@0: local gt, vid; wolffd@0: wolffd@0: gt = dotty.graphs[dotty.views[data.widget].gtid]; wolffd@0: for (vid in gt.views) { wolffd@0: vt = gt.views[vid]; wolffd@0: if (vt.type ~= 'birdseye') wolffd@0: gt.setviewcenter ([vid = vt;], data.pos); wolffd@0: } wolffd@0: }; wolffd@0: 'leftup' = function (data) { wolffd@0: local gt, vid; wolffd@0: wolffd@0: gt = dotty.graphs[dotty.views[data.widget].gtid]; wolffd@0: for (vid in gt.views) { wolffd@0: vt = gt.views[vid]; wolffd@0: if (vt.type ~= 'birdseye') wolffd@0: gt.setviewcenter ([vid = vt;], data.pos); wolffd@0: } wolffd@0: }; wolffd@0: 'middledown' = dotty.protovt.normal.uifuncs.middledown; wolffd@0: 'middlemove' = dotty.protovt.normal.uifuncs.middlemove; wolffd@0: 'middleup' = dotty.protovt.normal.uifuncs.middleup; wolffd@0: 'rightdown' = dotty.protovt.normal.uifuncs.rightdown; wolffd@0: 'keyup' = dotty.protovt.normal.uifuncs.keyup; wolffd@0: 'redraw' = dotty.protovt.normal.uifuncs.redraw; wolffd@0: 'closeview' = dotty.protovt.normal.uifuncs.closeview; wolffd@0: ]; wolffd@0: dotty.monitorfile = function (data) { wolffd@0: local gtid, gt, lpt; wolffd@0: wolffd@0: for (gtid in dotty.layoutpending) { wolffd@0: lpt = dotty.layoutpending[gtid]; wolffd@0: if (lpt.fd == data.fd) { wolffd@0: gt = dotty.graphs[lpt.gtid]; wolffd@0: gt.haveinput = 1; wolffd@0: gt.layoutgraph (gt); wolffd@0: return 1; wolffd@0: } wolffd@0: } wolffd@0: return 0; wolffd@0: };