annotate toolboxes/graph_visualisation/lib/lefty/dotty_edit.lefty @ 0:e9a9cd732c1e tip

first hg version after svn
author wolffd
date Tue, 10 Feb 2015 15:05:51 +0000
parents
children
rev   line source
wolffd@0 1 #
wolffd@0 2 # dotty_edit: editing functions and data structures
wolffd@0 3 #
wolffd@0 4 dotty.protogt.getnodesbyattr = function (gt, key, val) {
wolffd@0 5 local nid, node, nlist;
wolffd@0 6
wolffd@0 7 nlist = [];
wolffd@0 8 for (nid in gt.graph.nodes) {
wolffd@0 9 node = gt.graph.nodes[nid];
wolffd@0 10 if (node.attr[key] == val)
wolffd@0 11 nlist[nid] = node;
wolffd@0 12 }
wolffd@0 13 return nlist;
wolffd@0 14 };
wolffd@0 15 dotty.protogt.reachablenodes = function (gt, node) {
wolffd@0 16 local nlist, stack, eid, edge, i;
wolffd@0 17
wolffd@0 18 stack[0] = node;
wolffd@0 19 i = 1;
wolffd@0 20 while (i > 0) {
wolffd@0 21 node = stack[i - 1];
wolffd@0 22 i = i - 1;
wolffd@0 23 nlist[node.nid] = node;
wolffd@0 24 for (eid in node.edges) {
wolffd@0 25 edge = node.edges[eid];
wolffd@0 26 if (~nlist[edge.head.nid]) {
wolffd@0 27 nlist[edge.head.nid] = edge.head;
wolffd@0 28 stack[i] = edge.head;
wolffd@0 29 i = i + 1;
wolffd@0 30 }
wolffd@0 31 }
wolffd@0 32 }
wolffd@0 33 return nlist;
wolffd@0 34 };
wolffd@0 35 dotty.protogt.mergegraph = function (gt, graph, show) {
wolffd@0 36 local nameid, onode, pos, size, eid, eid2, tnode, hnode, oedge;
wolffd@0 37
wolffd@0 38 if (~gt.noundo)
wolffd@0 39 gt.startadd2undo (gt);
wolffd@0 40 for (nameid in graph.nodedict) {
wolffd@0 41 pos = null;
wolffd@0 42 size = null;
wolffd@0 43 onode = graph.nodes[graph.nodedict[nameid]];
wolffd@0 44 if (onode.pos)
wolffd@0 45 pos = node.pos;
wolffd@0 46 if (onode.size)
wolffd@0 47 size = node.size;
wolffd@0 48 if (~(gt.graph.nodedict[nameid] >= 0)) {
wolffd@0 49 pos = null;
wolffd@0 50 size = null;
wolffd@0 51 if (onode.pos)
wolffd@0 52 pos = node.pos;
wolffd@0 53 if (onode.size)
wolffd@0 54 size = node.size;
wolffd@0 55 gt.insertnode (gt, pos, size, nameid, onode.attr, show);
wolffd@0 56 }
wolffd@0 57 }
wolffd@0 58 for (eid in graph.edges) {
wolffd@0 59 oedge = graph.edges[eid];
wolffd@0 60 tnode = gt.graph.nodes[gt.graph.nodedict[oedge.tail.name]];
wolffd@0 61 hnode = gt.graph.nodes[gt.graph.nodedict[oedge.head.name]];
wolffd@0 62 for (eid2 in tnode.edges)
wolffd@0 63 if (
wolffd@0 64 tnode.edges[eid2].tail == tnode &
wolffd@0 65 tnode.edges[eid2].head == hnode
wolffd@0 66 ) {
wolffd@0 67 oedge = null;
wolffd@0 68 break;
wolffd@0 69 }
wolffd@0 70 if (oedge)
wolffd@0 71 gt.insertedge (gt, tnode, null, hnode, null, oedge.attr, show);
wolffd@0 72 }
wolffd@0 73 if (~gt.noundo)
wolffd@0 74 gt.endadd2undo (gt);
wolffd@0 75 };
wolffd@0 76 dotty.protogt.insertsgraph = function (gt, name, attr, show) {
wolffd@0 77 local gid, sgraph, aid;
wolffd@0 78
wolffd@0 79 if (~gt)
wolffd@0 80 return null;
wolffd@0 81 gid = gt.graph.maxgid;
wolffd@0 82 if (~name) {
wolffd@0 83 while (gt.graph.graphdict[(name = concat ('g', gid))] >= 0)
wolffd@0 84 gid = gid + 1;
wolffd@0 85 } else if (gt.graph.graphdict[name]) {
wolffd@0 86 dotty.message (0, concat ('graph: ', name, ' exists'));
wolffd@0 87 return null;
wolffd@0 88 }
wolffd@0 89 gt.graph.graphdict[name] = gid;
wolffd@0 90 gt.graph.maxgid = gid + 1;
wolffd@0 91 gt.graph.graphs[gid] = [
wolffd@0 92 dotty.keys.gid = gid;
wolffd@0 93 dotty.keys.name = name;
wolffd@0 94 dotty.keys.gattr = copy (gt.graph.graphattr);
wolffd@0 95 dotty.keys.nattr = copy (gt.graph.nodeattr);
wolffd@0 96 dotty.keys.eattr = copy (gt.graph.edgeattr);
wolffd@0 97 ];
wolffd@0 98 sgraph = gt.graph.graphs[gid];
wolffd@0 99 if (~attr)
wolffd@0 100 attr = [];
wolffd@0 101 if (~attr.label)
wolffd@0 102 attr.label = '\N';
wolffd@0 103 for (aid in attr)
wolffd@0 104 sgraph.graphattr[aid] = attr[aid];
wolffd@0 105 gt.unpacksgraphattr (gt, sgraph);
wolffd@0 106 if (show)
wolffd@0 107 gt.drawsgraph (gt, gt.views, sgraph);
wolffd@0 108 return sgraph;
wolffd@0 109 };
wolffd@0 110 dotty.protogt.removesgraph = function (gt, sgraph) {
wolffd@0 111 gt.undrawsgraph (gt, gt.views, sgraph);
wolffd@0 112 remove (sgraph.name, gt.graph.graphdict);
wolffd@0 113 remove (sgraph.gid, gt.graph.graphs);
wolffd@0 114 };
wolffd@0 115 dotty.protogt.insertnode = function (gt, pos, size, name, attr, show) {
wolffd@0 116 local nid, node, aid;
wolffd@0 117
wolffd@0 118 nid = gt.graph.maxnid;
wolffd@0 119 if (~name) {
wolffd@0 120 while (gt.graph.nodedict[(name = concat ('n', nid))] >= 0)
wolffd@0 121 nid = nid + 1;
wolffd@0 122 } else if (gt.graph.nodedict[name] >= 0) {
wolffd@0 123 dotty.message (0, concat ('node: ', name, ' exists'));
wolffd@0 124 return null;
wolffd@0 125 }
wolffd@0 126 gt.graph.nodedict[name] = nid;
wolffd@0 127 gt.graph.maxnid = nid + 1;
wolffd@0 128 gt.graph.nodes[nid] = [
wolffd@0 129 dotty.keys.nid = nid;
wolffd@0 130 dotty.keys.name = name;
wolffd@0 131 dotty.keys.attr = copy (gt.graph.nodeattr);
wolffd@0 132 dotty.keys.edges = [];
wolffd@0 133 ];
wolffd@0 134 node = gt.graph.nodes[nid];
wolffd@0 135 if (~attr)
wolffd@0 136 attr = [];
wolffd@0 137 if (~attr.label)
wolffd@0 138 attr.label = '\N';
wolffd@0 139 for (aid in attr)
wolffd@0 140 node.attr[aid] = attr[aid];
wolffd@0 141 gt.unpacknodeattr (gt, node);
wolffd@0 142 if (~pos)
wolffd@0 143 pos = ['x' = 10; 'y' = 10;];
wolffd@0 144 node[dotty.keys.pos] = copy (pos);
wolffd@0 145 if (~size)
wolffd@0 146 size = ['x' = strlen (attr.label) * 30; 'y' = 30;];
wolffd@0 147 if (size.x == 0)
wolffd@0 148 size.x = 30;
wolffd@0 149 node[dotty.keys.size] = copy (size);
wolffd@0 150 node[dotty.keys.rect] = [
wolffd@0 151 0 = ['x' = pos.x - size.x / 2; 'y' = pos.y - size.y / 2;];
wolffd@0 152 1 = ['x' = pos.x + size.x / 2; 'y' = pos.y + size.y / 2;];
wolffd@0 153 ];
wolffd@0 154 node.draws = gt.simplenodedraw (node, pos, size);
wolffd@0 155 if (show)
wolffd@0 156 gt.drawnode (gt, gt.views, node);
wolffd@0 157 if (~gt.noundo) {
wolffd@0 158 gt.startadd2undo (gt);
wolffd@0 159 gt.currundo.inserted.nodes[nid] = node;
wolffd@0 160 gt.endadd2undo (gt);
wolffd@0 161 }
wolffd@0 162 return node;
wolffd@0 163 };
wolffd@0 164 dotty.protogt.removenode = function (gt, node) {
wolffd@0 165 local eid, list, edge, gid;
wolffd@0 166
wolffd@0 167 if (~gt.noundo)
wolffd@0 168 gt.startadd2undo (gt);
wolffd@0 169 for (eid in node.edges)
wolffd@0 170 list[eid] = node.edges[eid];
wolffd@0 171 for (eid in list)
wolffd@0 172 gt.removeedge (gt, list[eid]);
wolffd@0 173 gt.undrawnode (gt, gt.views, node);
wolffd@0 174 for (gid in gt.graph.graphs)
wolffd@0 175 remove (node.nid, gt.graph.graphs[gid].nodes);
wolffd@0 176 remove (node.name, gt.graph.nodedict);
wolffd@0 177 remove (node.nid, gt.graph.nodes);
wolffd@0 178 if (~gt.noundo) {
wolffd@0 179 gt.currundo.deleted.nodes[node.nid] = node;
wolffd@0 180 gt.endadd2undo (gt);
wolffd@0 181 }
wolffd@0 182 };
wolffd@0 183 dotty.protogt.insertedge = function (
wolffd@0 184 gt, nodea, porta, nodeb, portb, attr, show
wolffd@0 185 ) {
wolffd@0 186 local eid, edge, aid, tport, hport;
wolffd@0 187
wolffd@0 188 if (~nodea | ~nodeb)
wolffd@0 189 return null;
wolffd@0 190 if (porta)
wolffd@0 191 tport = porta;
wolffd@0 192 if (portb)
wolffd@0 193 hport = portb;
wolffd@0 194 eid = gt.graph.maxeid;
wolffd@0 195 while (gt.graph.edges[eid])
wolffd@0 196 eid = eid + 1;
wolffd@0 197 gt.graph.maxeid = eid + 1;
wolffd@0 198 gt.graph.edges[eid] = [
wolffd@0 199 dotty.keys.eid = eid;
wolffd@0 200 dotty.keys.tail = nodea;
wolffd@0 201 dotty.keys.tport = porta;
wolffd@0 202 dotty.keys.head = nodeb;
wolffd@0 203 dotty.keys.hport = portb;
wolffd@0 204 dotty.keys.attr = copy (gt.graph.edgeattr);
wolffd@0 205 ];
wolffd@0 206 edge = gt.graph.edges[eid];
wolffd@0 207 if (~attr)
wolffd@0 208 attr = [];
wolffd@0 209 for (aid in attr)
wolffd@0 210 edge.attr[aid] = attr[aid];
wolffd@0 211 nodea.edges[eid] = edge;
wolffd@0 212 nodeb.edges[eid] = edge;
wolffd@0 213 gt.unpackedgeattr (gt, edge);
wolffd@0 214 edge.draws = gt.simpleedgedraw (edge, nodea.pos, nodeb.pos);
wolffd@0 215 if (show)
wolffd@0 216 gt.drawedge (gt, gt.views, edge);
wolffd@0 217 if (~gt.noundo) {
wolffd@0 218 gt.startadd2undo (gt);
wolffd@0 219 gt.currundo.inserted.edges[eid] = edge;
wolffd@0 220 gt.endadd2undo (gt);
wolffd@0 221 }
wolffd@0 222 return edge;
wolffd@0 223 };
wolffd@0 224 dotty.protogt.removeedge = function (gt, edge) {
wolffd@0 225 local head, tail;
wolffd@0 226
wolffd@0 227 if (~gt.noundo)
wolffd@0 228 gt.startadd2undo (gt);
wolffd@0 229 if (edge.head.attr.support == 1)
wolffd@0 230 head = edge.head;
wolffd@0 231 if (edge.tail.attr.support == 1)
wolffd@0 232 if (head ~= edge.tail)
wolffd@0 233 tail = edge.tail;
wolffd@0 234 gt.undrawedge (gt, gt.views, edge);
wolffd@0 235 remove (edge.eid, edge.head.edges);
wolffd@0 236 remove (edge.eid, edge.tail.edges);
wolffd@0 237 remove (edge.eid, gt.graph.edges);
wolffd@0 238 if (head & tablesize (head.edges) == 0)
wolffd@0 239 gt.removenode (gt, head);
wolffd@0 240 if (tail & tablesize (tail.edges) == 0)
wolffd@0 241 gt.removenode (gt, tail);
wolffd@0 242 if (~gt.noundo) {
wolffd@0 243 gt.currundo.deleted.edges[edge.eid] = edge;
wolffd@0 244 gt.endadd2undo (gt);
wolffd@0 245 }
wolffd@0 246 };
wolffd@0 247 dotty.protogt.swapedgeids = function (gt, edge1, edge2) {
wolffd@0 248 local eid1, eid2;
wolffd@0 249
wolffd@0 250 if (edge1.eid == edge2.eid)
wolffd@0 251 return;
wolffd@0 252 if (~gt.noundo)
wolffd@0 253 gt.startadd2undo (gt);
wolffd@0 254 eid1 = edge1.eid;
wolffd@0 255 eid2 = edge2.eid;
wolffd@0 256 gt.graph.edges[eid1] = edge2;
wolffd@0 257 gt.graph.edges[eid2] = edge1;
wolffd@0 258 remove (eid1, edge1.tail.edges);
wolffd@0 259 remove (eid1, edge1.head.edges);
wolffd@0 260 remove (eid2, edge2.tail.edges);
wolffd@0 261 remove (eid2, edge2.head.edges);
wolffd@0 262 edge1.tail.edges[eid2] = edge1;
wolffd@0 263 edge1.head.edges[eid2] = edge1;
wolffd@0 264 edge2.tail.edges[eid1] = edge2;
wolffd@0 265 edge2.head.edges[eid1] = edge2;
wolffd@0 266 edge1.eid = eid2;
wolffd@0 267 edge2.eid = eid1;
wolffd@0 268 if (~gt.noundo) {
wolffd@0 269 gt.currundo.swapped.edges[eid1] = edge1;
wolffd@0 270 gt.currundo.swapped.edges[eid2] = edge2;
wolffd@0 271 gt.endadd2undo (gt);
wolffd@0 272 }
wolffd@0 273 };
wolffd@0 274 dotty.protogt.removesubtree = function (gt, obj) {
wolffd@0 275 local nlist, node, head, nid, edge, eid;
wolffd@0 276
wolffd@0 277 if (~gt.noundo)
wolffd@0 278 gt.startadd2undo (gt);
wolffd@0 279 if (obj.nid >= 0)
wolffd@0 280 node = obj;
wolffd@0 281 else if (obj.eid >= 0) {
wolffd@0 282 node = obj.head;
wolffd@0 283 gt.removeedge (gt, obj);
wolffd@0 284 if (~gt.graph.nodes[node.nid]) {
wolffd@0 285 if (~gt.noundo)
wolffd@0 286 gt.endadd2undo (gt);
wolffd@0 287 return;
wolffd@0 288 }
wolffd@0 289 for (eid in node.edges) {
wolffd@0 290 edge = node.edges[eid];
wolffd@0 291 if (edge.head == node & edge.tail ~= node) {
wolffd@0 292 if (~gt.noundo)
wolffd@0 293 gt.endadd2undo (gt);
wolffd@0 294 return;
wolffd@0 295 }
wolffd@0 296 }
wolffd@0 297 } else {
wolffd@0 298 dotty.message (0, 'bad object type in gt.removesubtree');
wolffd@0 299 return;
wolffd@0 300 }
wolffd@0 301 nlist = [node.nid = node;];
wolffd@0 302 while (node) {
wolffd@0 303 for (eid in node.edges) {
wolffd@0 304 head = node.edges[eid].head;
wolffd@0 305 if (head ~= node)
wolffd@0 306 nlist[head.nid] = head;
wolffd@0 307 }
wolffd@0 308 gt.removenode (gt, node);
wolffd@0 309 remove (node.nid, nlist);
wolffd@0 310 node = null;
wolffd@0 311 for (nid in nlist) {
wolffd@0 312 node = nlist[nid];
wolffd@0 313 for (eid in node.edges) {
wolffd@0 314 edge = node.edges[eid];
wolffd@0 315 if (edge.head == node & edge.tail ~= node) {
wolffd@0 316 node = null;
wolffd@0 317 break;
wolffd@0 318 }
wolffd@0 319 }
wolffd@0 320 if (node)
wolffd@0 321 break;
wolffd@0 322 }
wolffd@0 323 }
wolffd@0 324 if (~gt.noundo)
wolffd@0 325 gt.endadd2undo (gt);
wolffd@0 326 };
wolffd@0 327 dotty.protogt.removenodesbyattr = function (gt, key, val) {
wolffd@0 328 local nlist, nid;
wolffd@0 329
wolffd@0 330 if (~gt.noundo)
wolffd@0 331 gt.startadd2undo (gt);
wolffd@0 332 nlist = gt.getnodesbyattr (gt, key, val);
wolffd@0 333 for (nid in nlist)
wolffd@0 334 gt.removenode (gt, nlist[nid]);
wolffd@0 335 if (~gt.noundo)
wolffd@0 336 gt.endadd2undo (gt);
wolffd@0 337 };
wolffd@0 338 dotty.protogt.removesubtreesbyattr = function (gt, key, val) {
wolffd@0 339 local nlist, nid;
wolffd@0 340
wolffd@0 341 if (~gt.noundo)
wolffd@0 342 gt.startadd2undo (gt);
wolffd@0 343 nlist = gt.getnodesbyattr (gt, key, val);
wolffd@0 344 for (nid in nlist)
wolffd@0 345 if (gt.graph.nodes[nid])
wolffd@0 346 gt.removesubtree (gt, nlist[nid]);
wolffd@0 347 if (~gt.noundo)
wolffd@0 348 gt.endadd2undo (gt);
wolffd@0 349 };
wolffd@0 350 dotty.protogt.groupnodes = function (
wolffd@0 351 gt, nlist, gnode, pos, size, attr, keepmulti, show
wolffd@0 352 ) {
wolffd@0 353 local nid, node, elist, eid, edge, nodea, nodeb, inlist, outlist;
wolffd@0 354
wolffd@0 355 if (~nlist | tablesize (nlist) == 0)
wolffd@0 356 return;
wolffd@0 357 if (gnode.attr.support) {
wolffd@0 358 dotty.message (0, 'cannot group nodes in a support node');
wolffd@0 359 return;
wolffd@0 360 }
wolffd@0 361 if (~gt.noundo)
wolffd@0 362 gt.startadd2undo (gt);
wolffd@0 363 if (~gnode)
wolffd@0 364 gnode = gt.insertnode (gt, pos, size, null, attr, show);
wolffd@0 365 inlist = [];
wolffd@0 366 outlist = [];
wolffd@0 367 for (nid in nlist) {
wolffd@0 368 if ((node = nlist[nid]) == gnode)
wolffd@0 369 continue;
wolffd@0 370 elist = [];
wolffd@0 371 for (eid in node.edges)
wolffd@0 372 elist[eid] = node.edges[eid];
wolffd@0 373 for (eid in elist) {
wolffd@0 374 edge = elist[eid];
wolffd@0 375 if (edge.head == node) {
wolffd@0 376 nodea = edge.tail;
wolffd@0 377 nodeb = gnode;
wolffd@0 378 if (~keepmulti) {
wolffd@0 379 if (inlist[nodea.nid])
wolffd@0 380 continue;
wolffd@0 381 inlist[nodea.nid] = nodea;
wolffd@0 382 if (nodea == gnode)
wolffd@0 383 outlist[nodea.nid] = nodea;
wolffd@0 384 }
wolffd@0 385 } else {
wolffd@0 386 nodea = gnode;
wolffd@0 387 nodeb = edge.head;
wolffd@0 388 if (~keepmulti) {
wolffd@0 389 if (outlist[nodeb.nid])
wolffd@0 390 continue;
wolffd@0 391 outlist[nodeb.nid] = nodeb;
wolffd@0 392 if (nodeb == gnode)
wolffd@0 393 inlist[nodeb.nid] = nodeb;
wolffd@0 394 }
wolffd@0 395 }
wolffd@0 396 gt.insertedge (gt, nodea, null, nodeb, null, edge.attr, show);
wolffd@0 397 }
wolffd@0 398 gt.removenode (gt, node);
wolffd@0 399 }
wolffd@0 400 if (~gt.noundo)
wolffd@0 401 gt.endadd2undo (gt);
wolffd@0 402 return gnode;
wolffd@0 403 };
wolffd@0 404 dotty.protogt.groupnodesbyattr = function (
wolffd@0 405 gt, key, val, attr, keepmulti, show
wolffd@0 406 ) {
wolffd@0 407 local nlist, nid, pos, size;
wolffd@0 408
wolffd@0 409 pos = null;
wolffd@0 410 size = null;
wolffd@0 411 nlist = gt.getnodesbyattr (gt, key, val);
wolffd@0 412 if (show)
wolffd@0 413 for (nid in nlist) {
wolffd@0 414 pos = nlist[nid].pos;
wolffd@0 415 size = nlist[nid].size;
wolffd@0 416 break;
wolffd@0 417 }
wolffd@0 418 return gt.groupnodes (gt, nlist, null, pos, size, attr, keepmulti, show);
wolffd@0 419 };
wolffd@0 420 dotty.protogt.cut = function (gt, obj, set, mode, op) {
wolffd@0 421 local clipgt, list, node, nid, edge, eid, clipnode;
wolffd@0 422
wolffd@0 423 clipgt = dotty.clipgt;
wolffd@0 424 clipgt.graph = copy (dotty.protogt.graph);
wolffd@0 425 if (obj.eid >= 0) { # it's an edge
wolffd@0 426 list.edges[obj.eid] = obj;
wolffd@0 427 node = obj.head;
wolffd@0 428 } else if (obj.nid >= 0) {
wolffd@0 429 list.nodes[obj.nid] = obj;
wolffd@0 430 node = obj;
wolffd@0 431 for (eid in node.edges)
wolffd@0 432 list.edges[eid] = node.edges[eid];
wolffd@0 433 } else {
wolffd@0 434 dotty.message (0, 'unknown object type in gt.cut');
wolffd@0 435 return;
wolffd@0 436 }
wolffd@0 437 if (set == 'reachable') {
wolffd@0 438 list.nodes = gt.reachablenodes (gt, node);
wolffd@0 439 for (nid in list.nodes) {
wolffd@0 440 node = list.nodes[nid];
wolffd@0 441 for (eid in node.edges) {
wolffd@0 442 edge = node.edges[eid];
wolffd@0 443 list.edges[edge.eid] = edge;
wolffd@0 444 }
wolffd@0 445 }
wolffd@0 446 }
wolffd@0 447 if (mode == 'support') {
wolffd@0 448 for (eid in list.edges) {
wolffd@0 449 edge = list.edges[eid];
wolffd@0 450 if (~list.nodes[edge.tail.nid]) {
wolffd@0 451 list.support[edge.tail.nid] = edge.tail;
wolffd@0 452 list.nodes[edge.tail.nid] = edge.tail;
wolffd@0 453 }
wolffd@0 454 if (~list.nodes[edge.head.nid]) {
wolffd@0 455 list.support[edge.head.nid] = edge.head;
wolffd@0 456 list.nodes[edge.head.nid] = edge.head;
wolffd@0 457 }
wolffd@0 458 }
wolffd@0 459 }
wolffd@0 460 for (nid = 0; nid < gt.graph.maxnid; nid = nid + 1) {
wolffd@0 461 if (~list.nodes[nid])
wolffd@0 462 continue;
wolffd@0 463 node = list.nodes[nid];
wolffd@0 464 clipnode = gt.insertnode (clipgt, null, null, node.name, node.attr, 0);
wolffd@0 465 if (list.support[nid])
wolffd@0 466 clipnode.support = 1;
wolffd@0 467 list.clipnodes[nid] = clipnode;
wolffd@0 468 }
wolffd@0 469 for (eid = 0; eid < gt.graph.maxeid; eid = eid + 1) {
wolffd@0 470 if (~list.edges[eid])
wolffd@0 471 continue;
wolffd@0 472 edge = list.edges[eid];
wolffd@0 473 if (~list.nodes[edge.tail.nid] | ~list.nodes[edge.head.nid])
wolffd@0 474 continue;
wolffd@0 475 gt.insertedge (
wolffd@0 476 clipgt, list.clipnodes[edge.tail.nid], null,
wolffd@0 477 list.clipnodes[edge.head.nid], null, edge.attr, 0
wolffd@0 478 );
wolffd@0 479 }
wolffd@0 480 if (op ~= 'cut')
wolffd@0 481 return;
wolffd@0 482 if (~gt.noundo)
wolffd@0 483 gt.startadd2undo (gt);
wolffd@0 484 for (eid in list.edges)
wolffd@0 485 gt.removeedge (gt, list.edges[eid]);
wolffd@0 486 for (nid in list.nodes)
wolffd@0 487 if (~list.support[nid] & gt.graph.nodes[nid])
wolffd@0 488 gt.removenode (gt, list.nodes[nid]);
wolffd@0 489 if (~gt.noundo)
wolffd@0 490 gt.endadd2undo (gt);
wolffd@0 491 };
wolffd@0 492 dotty.protogt.paste = function (gt, pos, show) {
wolffd@0 493 local clipgt, offset, center, nid, node, eid, edge, nodes;
wolffd@0 494
wolffd@0 495 if (~gt.noundo)
wolffd@0 496 gt.startadd2undo (gt);
wolffd@0 497 clipgt = dotty.clipgt;
wolffd@0 498 if (clipgt.graph.rect)
wolffd@0 499 center = [
wolffd@0 500 'x' = (clipgt.graph.rect[1].x + clipgt.graph.rect[0].x) / 2;
wolffd@0 501 'y' = (clipgt.graph.rect[1].y + clipgt.graph.rect[0].y) / 2;
wolffd@0 502 ];
wolffd@0 503 else
wolffd@0 504 center = pos;
wolffd@0 505 offset = [
wolffd@0 506 'x' = center.x - pos.x;
wolffd@0 507 'y' = center.y - pos.y;
wolffd@0 508 ];
wolffd@0 509 for (nid = 0; clipgt.graph.nodes[nid]; nid = nid + 1) {
wolffd@0 510 node = clipgt.graph.nodes[nid];
wolffd@0 511 if (node.attr.label == '\N' | ~node.attr.label)
wolffd@0 512 node.attr.label = node.name;
wolffd@0 513 if (node.support == 1)
wolffd@0 514 nodes[nid] = gt.insertnode (gt, [
wolffd@0 515 'x' = node.pos.x - offset.x;
wolffd@0 516 'y' = node.pos.y - offset.y;
wolffd@0 517 ], null, null, [
wolffd@0 518 'support' = 1; 'shape' = 'circle';
wolffd@0 519 'label' = ''; 'width' = 0.2;
wolffd@0 520 ], show);
wolffd@0 521 else
wolffd@0 522 nodes[nid] = gt.insertnode (gt, [
wolffd@0 523 'x' = node.pos.x - offset.x;
wolffd@0 524 'y' = node.pos.y - offset.y;
wolffd@0 525 ], node.size, null, node.attr, show);
wolffd@0 526 }
wolffd@0 527 for (eid = 0; clipgt.graph.edges[eid]; eid = eid + 1) {
wolffd@0 528 edge = clipgt.graph.edges[eid];
wolffd@0 529 gt.insertedge (
wolffd@0 530 gt, nodes[edge.tail.nid], null,
wolffd@0 531 nodes[edge.head.nid], null, edge.attr, show
wolffd@0 532 );
wolffd@0 533 }
wolffd@0 534 if (~gt.noundo)
wolffd@0 535 gt.endadd2undo (gt);
wolffd@0 536 };
wolffd@0 537 dotty.protogt.startadd2undo = function (gt) {
wolffd@0 538 if (~gt.undoarray.level)
wolffd@0 539 gt.currundo = (
wolffd@0 540 gt.undoarray.entries[tablesize (gt.undoarray.entries)] = []
wolffd@0 541 );
wolffd@0 542 gt.undoarray.level = gt.undoarray.level + 1;
wolffd@0 543 };
wolffd@0 544 dotty.protogt.endadd2undo = function (gt) {
wolffd@0 545 gt.undoarray.level = gt.undoarray.level - 1;
wolffd@0 546 };
wolffd@0 547 dotty.protogt.undo = function (gt, show) {
wolffd@0 548 local entry, n, eid, edge, nid, node, edges;
wolffd@0 549
wolffd@0 550 if ((n = tablesize (gt.undoarray.entries)) < 1)
wolffd@0 551 return;
wolffd@0 552 entry = gt.undoarray.entries[n - 1];
wolffd@0 553 remove (n - 1, gt.undoarray.entries);
wolffd@0 554 remove ('currundo', gt);
wolffd@0 555 gt.noundo = 1;
wolffd@0 556 # hardwire nodes and edges back with the same id's as the originals
wolffd@0 557 for (nid in entry.deleted.nodes) {
wolffd@0 558 node = entry.deleted.nodes[nid];
wolffd@0 559 gt.graph.nodedict[node.name] = node.nid;
wolffd@0 560 gt.graph.nodes[node.nid] = node;
wolffd@0 561 node.edges = [];
wolffd@0 562 if (show)
wolffd@0 563 gt.drawnode (gt, gt.views, node);
wolffd@0 564 }
wolffd@0 565 for (eid in entry.deleted.edges) {
wolffd@0 566 edge = entry.deleted.edges[eid];
wolffd@0 567 gt.graph.edges[edge.eid] = edge;
wolffd@0 568 edge.head.edges[edge.eid] = edge;
wolffd@0 569 edge.tail.edges[edge.eid] = edge;
wolffd@0 570 if (show)
wolffd@0 571 gt.drawedge (gt, gt.views, edge);
wolffd@0 572 }
wolffd@0 573 if (entry.swapped.edges) {
wolffd@0 574 if (tablesize (entry.swapped.edges) == 2) {
wolffd@0 575 n = 0;
wolffd@0 576 for (eid in entry.swapped.edges) {
wolffd@0 577 edges[n] = entry.swapped.edges[eid];
wolffd@0 578 n = n + 1;
wolffd@0 579 }
wolffd@0 580 gt.swapedgeids (gt, edges[0], edges[1]);
wolffd@0 581 } else
wolffd@0 582 dotty.message (0, 'cannot handle undoing swap of > 2 edges');
wolffd@0 583 }
wolffd@0 584 for (eid in entry.inserted.edges) {
wolffd@0 585 edge = entry.inserted.edges[eid];
wolffd@0 586 gt.removeedge (gt, edge);
wolffd@0 587 }
wolffd@0 588 for (nid in entry.inserted.nodes) {
wolffd@0 589 node = entry.inserted.nodes[nid];
wolffd@0 590 gt.removenode (gt, node);
wolffd@0 591 }
wolffd@0 592 gt.noundo = 0;
wolffd@0 593 };