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