1function mxGraphMlCodec() 2{ 3 this.cachedRefObj = {}; 4}; 5 6 7mxGraphMlCodec.prototype.refRegexp = /^\{y\:GraphMLReference\s+(\d+)\}$/; 8mxGraphMlCodec.prototype.staticRegexp = /^\{x\:Static\s+(.+)\.(.+)\}$/; 9 10mxGraphMlCodec.prototype.decode = function (xml, callback, onError) 11{ 12 try 13 { 14 var doc = mxUtils.parseXml(xml); 15 16 var graphs = this.getDirectChildNamedElements(doc.documentElement, mxGraphMlConstants.GRAPH); 17 18 this.initializeKeys(doc.documentElement); 19 20 var mxFile = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><mxfile>"; 21 for (var i = 0; i < graphs.length; i++) 22 { 23 var pageElement = graphs[i]; 24 25 var graph = this.createMxGraph(); 26 var model = graph.getModel(); 27 28 model.beginUpdate(); 29 try 30 { 31 this.nodesMap = {}; 32 this.edges = []; 33 this.importGraph(pageElement, graph, graph.getDefaultParent()); 34 35 for (var i = 0; i < this.edges.length; i++) 36 { 37 var edgesObj = this.edges[i]; 38 var edges = edgesObj.edges; 39 var parent = edgesObj.parent; 40 var dx = edgesObj.dx, dy = edgesObj.dy; 41 42 for (var j = 0; j < edges.length; j++) 43 { 44 this.importEdge(edges[j], graph, parent, dx, dy); 45 } 46 } 47 } 48 catch(e) 49 { 50 console.log(e); 51 throw e; 52 } 53 finally 54 { 55 model.endUpdate(); 56 } 57 58 //update edges' labels to convert their labels relative coordinate to ours 59 model.beginUpdate(); 60 try 61 { 62 var cells = graph.getModel().cells; 63 var tr = graph.view.translate; 64 65 for (var id in cells) 66 { 67 var edge = cells[id]; 68 69 if (edge.edge && edge.getChildCount() > 0) 70 { 71 for (var i = 0; i < edge.getChildCount(); i++) 72 { 73 var cell = edge.children[i]; 74 var geo = cell.geometry; 75 76 if (!geo.adjustIt) continue; 77 78 var state = graph.view.getState(edge); 79 var abdPs = state.absolutePoints; 80 var p0 = abdPs[0]; 81 var pe = abdPs[abdPs.length - 1]; 82 83 var ratio = geo.x; 84 var dist = geo.y; 85 var dx = pe.x - p0.x 86 var dy = pe.y - p0.y 87 88 var x = p0.x + ratio * dx; 89 var y = p0.y + ratio * dy; 90 91 var d = Math.sqrt(dx*dx + dy*dy); 92 dx /= d; 93 dy /= d; 94 95 x -= dist * dy; 96 y += dist * dx; 97 98 var np = graph.view.getRelativePoint(state, x, y); 99 geo.x = np.x; 100 geo.y = np.y; 101 } 102 } 103 } 104 } 105 catch(e) 106 { 107 console.log(e); 108 throw e; 109 } 110 finally 111 { 112 model.endUpdate(); 113 } 114 115 mxFile += this.processPage(graph, i+1); 116 } 117 118 mxFile += "</mxfile>"; 119 120 if (callback) 121 { 122 callback(mxFile); 123 } 124 } 125 catch(e) 126 { 127 if (onError) 128 { 129 onError(e); 130 } 131 } 132}; 133 134mxGraphMlCodec.prototype.initializeKeys = function (graphmlElement) 135{ 136 var keys = this.getDirectChildNamedElements(graphmlElement, mxGraphMlConstants.KEY); 137 138 this.nodesKeys = {}; 139 this.edgesKeys = {}; 140 this.portsKeys = {}; 141 this.sharedData = {}; 142 143 this.nodesKeys[mxGraphMlConstants.NODE_GEOMETRY] = {}; 144 this.nodesKeys[mxGraphMlConstants.USER_TAGS] = {}; 145 this.nodesKeys[mxGraphMlConstants.NODE_STYLE] = {}; 146 this.nodesKeys[mxGraphMlConstants.NODE_LABELS] = {}; 147 this.nodesKeys[mxGraphMlConstants.NODE_GRAPHICS] = {}; 148 this.edgesKeys[mxGraphMlConstants.EDGE_GEOMETRY] = {}; 149 this.edgesKeys[mxGraphMlConstants.EDGE_STYLE] = {}; 150 this.edgesKeys[mxGraphMlConstants.EDGE_LABELS] = {}; 151 this.portsKeys[mxGraphMlConstants.PORT_LOCATION_PARAMETER] = {}; 152 this.portsKeys[mxGraphMlConstants.PORT_STYLE] = {}; 153 this.portsKeys[mxGraphMlConstants.PORT_VIEW_STATE] = {}; 154 155 var sharedDataId; 156 157 for (var i = 0; i < keys.length; i++) 158 { 159 var keyObj = this.dataElem2Obj(keys[i]); 160 161 var id = keyObj[mxGraphMlConstants.ID]; 162 var _for = keyObj[mxGraphMlConstants.KEY_FOR]; 163 var attName = keyObj[mxGraphMlConstants.KEY_NAME]; 164 var yType = keyObj[mxGraphMlConstants.KEY_YTYPE]; 165 166 if (attName == mxGraphMlConstants.SHARED_DATA) sharedDataId = id; 167 168 attName = attName? attName : yType 169 170 //TODO handle the defaults inside these keys 171 switch (_for) 172 { 173 case mxGraphMlConstants.NODE: 174 this.nodesKeys[attName] = {key: id, keyObj: keyObj}; 175 break; 176 case mxGraphMlConstants.EDGE: 177 this.edgesKeys[attName] = {key: id, keyObj: keyObj}; 178 break; 179 case mxGraphMlConstants.PORT: 180 this.portsKeys[attName] = {key: id, keyObj: keyObj}; 181 break; 182 case mxGraphMlConstants.ALL: 183 var obj = {key: id, keyObj: keyObj}; 184 this.nodesKeys[attName] = obj; 185 this.edgesKeys[attName] = obj; 186 this.portsKeys[attName] = obj; 187 break; 188 } 189 } 190 191 var data = this.getDirectChildNamedElements(graphmlElement, mxGraphMlConstants.DATA); 192 193 for (var i = 0; i < data.length; i++) 194 { 195 var key = data[i].getAttribute(mxGraphMlConstants.KEY); 196 197 if (key == sharedDataId) 198 { 199 var sharedData = this.getDirectChildNamedElements(data[i], mxGraphMlConstants.Y_SHARED_DATA); 200 201 for (var j = 0; j < sharedData.length; j++) 202 { 203 var dataItems = this.getDirectChildElements(sharedData[j]); 204 205 for (var k = 0; k < dataItems.length; k++) 206 { 207 var dkey = dataItems[k].getAttribute(mxGraphMlConstants.X_KEY); 208 this.sharedData[dkey] = dataItems[k]; 209 } 210 } 211 } 212 else 213 { 214 var resources = this.getDirectChildNamedElements(data[i], mxGraphMlConstants.Y_RESOURCES); 215 216 for (var j = 0; j < resources.length; j++) 217 { 218 var dataItems = this.getDirectChildElements(resources[j]); 219 220 for (var k = 0; k < dataItems.length; k++) 221 { 222 var dkey = dataItems[k].getAttribute(mxGraphMlConstants.ID); 223 this.sharedData[dkey] = dataItems[k]; 224 } 225 } 226 } 227 } 228}; 229 230mxGraphMlCodec.prototype.parseAttributes = function (elem, obj) 231{ 232 var atts = elem.attributes; 233 if (atts) 234 { 235 236 for (var i = 0; i < atts.length; i++) 237 { 238 var val = atts[i].nodeValue; 239 var ref = this.refRegexp.exec(val); 240 var staticMem = this.staticRegexp.exec(val); 241 242 if (ref) 243 { 244 var key = ref[1]; 245 var subObj = this.cachedRefObj[key]; 246 247 //already cached 248 if (!subObj) 249 { 250 subObj = {}; 251 subObj[this.sharedData[key].nodeName] = this.dataElem2Obj(this.sharedData[key]); 252 this.cachedRefObj[key] = subObj; 253 } 254 255 obj[atts[i].nodeName] = subObj; 256 } 257 else if (staticMem) 258 { 259 obj[atts[i].nodeName] = {}; 260 obj[atts[i].nodeName][staticMem[1]] = staticMem[2]; 261 } 262 else 263 { 264 obj[atts[i].nodeName] = val; 265 } 266 } 267 } 268}; 269 270mxGraphMlCodec.prototype.dataElem2Obj = function (elem) 271{ 272 var ref = this.getDirectFirstChildNamedElements(elem, mxGraphMlConstants.GRAPHML_REFERENCE) 273 || elem.getAttribute(mxGraphMlConstants.REFID); 274 var refKey = null; 275 var origElem = elem; 276 var obj = {}; 277 278 if (ref) 279 { 280 var key = (typeof ref === "string")? ref : ref.getAttribute(mxGraphMlConstants.RESOURCE_KEY); 281 var cachedObj = this.cachedRefObj[key]; 282 283 //already cached 284 if (cachedObj) 285 { 286 //parse all attributes to update the reference 287 this.parseAttributes(elem, cachedObj); 288 return cachedObj; 289 } 290 291 elem = this.sharedData[key]; 292 refKey = key; 293 } 294 295 //parse all attributes 296 this.parseAttributes(elem, obj); 297 298 for (var i = 0; i < elem.childNodes.length; i++) 299 { 300 var child = elem.childNodes[i]; 301 302 if (child.nodeType == 1) 303 { 304 var attName = child.nodeName; 305 306 //Special types of node (x:List and x:Static) 307 if (attName == mxGraphMlConstants.X_LIST) 308 { 309 var arr = []; 310 var arrayElem = this.getDirectChildElements(child); 311 312 for (var j = 0; j < arrayElem.length; j++) 313 { 314 attName = arrayElem[j].nodeName; 315 arr.push(this.dataElem2Obj(arrayElem[j])); 316 } 317 318 obj[attName] = arr; 319 } 320 else if (attName == mxGraphMlConstants.X_STATIC) 321 { 322 var member = child.getAttribute(mxGraphMlConstants.MEMBER); 323 var dotPos = member.lastIndexOf('.'); 324 obj[member.substr(0, dotPos)] = member.substr(dotPos + 1); 325 } 326 else 327 { 328 var dotPos = attName.lastIndexOf("."); 329 330 if (dotPos > 0) 331 { 332 attName = attName.substr(dotPos + 1); 333 } 334 335 if (obj[attName] != null) 336 { 337 if (!(obj[attName] instanceof Array)) 338 { 339 obj[attName] = [obj[attName]]; 340 } 341 342 obj[attName].push(this.dataElem2Obj(child)); 343 } 344 else 345 { 346 obj[attName] = this.dataElem2Obj(child); 347 } 348 } 349 } 350 else if ((child.nodeType == 3 || child.nodeType == 4) && child.textContent.trim()) 351 { 352 obj["#text"] = child.textContent; 353 } 354 } 355 356 //cache referenced objects 357 if (refKey) 358 { 359 var tmpObj = {}; 360 //parse all attributes before following the reference 361 this.parseAttributes(origElem, tmpObj); 362 tmpObj[this.sharedData[refKey].nodeName] = obj; 363 this.cachedRefObj[refKey] = tmpObj; 364 return tmpObj; 365 } 366 367 return obj; 368}; 369 370mxGraphMlCodec.prototype.mapArray = function(arr, mapping, map) 371{ 372 var obj = {}; 373 for (var k = 0; k < arr.length; k++) 374 { 375 if (arr[k].name) 376 { 377 obj[arr[k].name] = arr[k].value || arr[k]; 378 } 379 } 380 this.mapObject(obj, mapping, map); 381} 382//Use mapping information to fill the map based on obj content 383//TODO yjs looks like they need special handling 384mxGraphMlCodec.prototype.mapObject = function (obj, mapping, map) 385{ 386 //defaults can be overridden by actual values later 387 if (mapping.defaults) 388 { 389 for (var key in mapping.defaults) 390 { 391 map[key] = mapping.defaults[key]; 392 } 393 } 394 395 for (var key in mapping) 396 { 397 var parts = key.split('.'); 398 399 var val = obj; 400 401 for (var i = 0; i < parts.length; i++) 402 { 403 if (!val) break; 404 405 val = val[parts[i]]; 406 } 407 408 if (val == null && obj) //some vals doesn't need to be split 409 { 410 val = obj[key]; 411 } 412 413 if (val != null) 414 { 415 var mappingObj = mapping[key]; 416 if (typeof val === "string") 417 { 418 if (typeof mappingObj === "string") 419 { 420 map[mappingObj] = val.toLowerCase(); 421 } 422 else if (typeof mappingObj === "object") 423 { 424 var modVal = val.toLowerCase(); 425 switch(mappingObj.mod) 426 { 427 case "color": //mxGraph support alfa in colors in the standard format 428 if (val.indexOf("#") == 0 && val.length == 9) 429 { 430 modVal = "#" + val.substr(3) + val.substr(1,2); 431 } 432 else if (val == "TRANSPARENT") 433 { 434 modVal = "none"; 435 } 436 break; 437 case "shape": 438// console.log(val.toLowerCase()); 439 modVal = mxGraphMlShapesMap[val.toLowerCase()]; 440 break; 441 case "bpmnOutline": 442// console.log(val.toLowerCase()); 443 modVal = mxGraphMlShapesMap.bpmnOutline[val.toLowerCase()]; 444 break; 445 case "bpmnSymbol": 446// console.log(val.toLowerCase()); 447 modVal = mxGraphMlShapesMap.bpmnSymbol[val.toLowerCase()]; 448 break; 449 case "bool": 450 modVal = val == "true"? "1" : "0"; 451 break; 452 case "scale": 453 try { 454 modVal = parseFloat(val) * mappingObj.scale; 455 } catch(e) { 456 //nothing! 457 } 458 break; 459 case "arrow": 460 modVal = mxGraphMlArrowsMap[val]; 461 break; 462 } 463 if (modVal != null) 464 map[mappingObj.key] = modVal; 465 } 466 else 467 { 468 mappingObj(val, map); 469 } 470 } 471 else if (val instanceof Array) 472 { 473 this.mapArray(val, mappingObj, map); 474 } 475 else if (val.name != null && val.value != null) //this is the case when a single y:Property is used 476 { 477 this.mapArray([val], mappingObj, map); 478 } 479 else 480 { 481 this.mapObject(val, mappingObj, map); 482 } 483 } 484 } 485}; 486 487mxGraphMlCodec.prototype.createMxGraph = function () 488{ 489 var graph = new mxGraph(); 490// graph.setExtendParents(false); 491// graph.setExtendParentsOnAdd(false); 492// graph.setConstrainChildren(false); 493// graph.setHtmlLabels(true); 494// graph.getModel().maintainEdgeParent = false; 495 return graph; 496} 497 498mxGraphMlCodec.prototype.importGraph = function (pageElement, graph, parent) 499{ 500 var nodes = this.getDirectChildNamedElements(pageElement, mxGraphMlConstants.NODE); 501 502 var p = parent; 503 var dx = 0, dy = 0; 504 while (p && p.geometry) 505 { 506 dx += p.geometry.x; 507 dy += p.geometry.y; 508 509 p = p.parent; 510 } 511 512 for (var i = 0; i < nodes.length; i++) 513 { 514 this.importNode(nodes[i], graph, parent, dx, dy); 515 } 516 517 this.edges.push({ 518 edges: this.getDirectChildNamedElements(pageElement, mxGraphMlConstants.EDGE), 519 parent: parent, 520 dx: dx, 521 dy: dy 522 }); 523}; 524 525//FIXME port 0.5, 0.5 push the edge to the other side (bpmn example) 526mxGraphMlCodec.prototype.importPort = function (portElement, portsMap) 527{ 528 var name = portElement.getAttribute(mxGraphMlConstants.PORT_NAME); 529 var portObj = {}; 530 531 var data = this.getDirectChildNamedElements(portElement, mxGraphMlConstants.DATA); 532 533 for (var i = 0; i < data.length; i++) 534 { 535 var d = data[i]; 536 var key = d.getAttribute(mxGraphMlConstants.KEY); 537 538 var dataObj = this.dataElem2Obj(d); 539// console.log(dataObj); 540 if (dataObj.key == this.portsKeys[mxGraphMlConstants.PORT_LOCATION_PARAMETER].key) 541 { 542 this.mapObject(dataObj, { 543 "y:FreeNodePortLocationModelParameter.Ratio": function(val, map) 544 { 545 var parts = val.split(','); 546 map["pos"] = {x: parts[0], y: parts[1]}; 547 } 548 }, portObj); 549 } 550 /* 551 else if (dataObj.key == this.portsKeys[mxGraphMlConstants.PORT_STYLE].key) 552 { 553 554 } 555 else if (dataObj.key == this.portsKeys[mxGraphMlConstants.PORT_VIEW_STATE].key) 556 { 557 558 }*/ 559 } 560 561 portsMap[name] = portObj; 562}; 563 564mxGraphMlCodec.prototype.styleMap2Str = function (styleMap) 565{ 566 var semi = ""; 567 var str = ""; 568 569 for (var key in styleMap) 570 { 571 str += semi + key + "=" + styleMap[key]; 572 semi = ";"; 573 } 574 575 return str; 576}; 577 578mxGraphMlCodec.prototype.importNode = function (nodeElement, graph, parent, dx, dy) 579{ 580 var data = this.getDirectChildNamedElements(nodeElement, mxGraphMlConstants.DATA); 581 var v; 582 var id = nodeElement.getAttribute(mxGraphMlConstants.ID); 583 584 var node = new mxCell(); 585 node.vertex = true; 586 node.geometry = new mxGeometry(0,0,30,30); //some node has no geometry, this is the default 587 588 graph.addCell(node, parent); 589 590 var style = {graphMlID: id}; 591 var mlStyleObj = null; 592 var mlTemplate = null; 593 var mlUserTags = null; 594 var lblObj = null; 595 var lbls = null; 596 597 for (var i = 0; i < data.length; i++) 598 { 599 var d = data[i]; 600 var dataObj = this.dataElem2Obj(d); 601 602 if (dataObj.key) 603 { 604 if (dataObj.key == this.nodesKeys[mxGraphMlConstants.NODE_GEOMETRY].key) 605 { 606 this.addNodeGeo(node, dataObj, dx, dy); 607 } 608 else if (dataObj.key == this.nodesKeys[mxGraphMlConstants.USER_TAGS].key) 609 { 610 mlUserTags = dataObj; 611 } 612 else if (dataObj.key == this.nodesKeys[mxGraphMlConstants.NODE_STYLE].key) 613 { 614 // console.log(JSON.stringify(dataObj)); 615 mlStyleObj = dataObj; 616 if (dataObj["yjs:StringTemplateNodeStyle"]) 617 { 618 mlTemplate = dataObj["yjs:StringTemplateNodeStyle"]["#text"]; 619 } 620 else 621 { 622 this.addNodeStyle(node, dataObj, style); 623 } 624 } 625 else if (dataObj.key == this.nodesKeys[mxGraphMlConstants.NODE_LABELS].key) 626 { 627 lblObj = dataObj; 628 } 629 else if (dataObj.key == this.nodesKeys[mxGraphMlConstants.NODE_GRAPHICS].key) 630 { 631 var shape = null, key = null; 632 for (var key in dataObj) 633 { 634 if (key == "key" || key == "#text") continue; 635 636 //Special case when a node has multiple graphics 637 //TODO support the open/closed states 638 if (key == "y:ProxyAutoBoundsNode") 639 { 640 var realizers = dataObj[key]["y:Realizers"]; 641 if (realizers) 642 { 643 for (var key2 in realizers) 644 { 645 if (key2 == "active" || key2 == "#text") continue; 646 647 shape = realizers[key2][realizers["active"]]; 648 dataObj = {}; 649 dataObj[key2] = shape; 650 break; 651 } 652 } 653 } 654 else 655 { 656 shape = dataObj[key]; 657 } 658 break; 659 } 660 if (shape) 661 { 662 if (shape[mxGraphMlConstants.GEOMETRY]) 663 { 664 this.addNodeGeo(node, shape[mxGraphMlConstants.GEOMETRY], dx, dy); 665 } 666 667 if (shape[mxGraphMlConstants.NODE_LABEL]) 668 { 669 lblObj = shape[mxGraphMlConstants.NODE_LABEL]; 670 } 671 } 672 mlStyleObj = dataObj; 673 this.addNodeStyle(node, dataObj, style); 674 } 675 } 676 } 677 678 var ports = this.getDirectChildNamedElements(nodeElement, mxGraphMlConstants.PORT); 679 var portsMap = {}; 680 681 for (var i = 0; i < ports.length; i++) 682 { 683 this.importPort(ports[i], portsMap); 684 } 685 686 if (mlTemplate) 687 { 688 this.handleTemplates(mlTemplate, mlUserTags, node, style); 689 } 690 691 this.handleFixedRatio(node, style); 692 693 //handle special compound shapes 694 this.handleCompoundShape(node, style, mlStyleObj, lbls); 695 696 //fix for stroke size of zero 697 if (style["strokeWidth"] == 0) 698 { 699 style["strokeColor"] = "none"; 700 } 701 702 node.style = this.styleMap2Str(style); 703 704 var subGraphs = this.getDirectChildNamedElements(nodeElement, mxGraphMlConstants.GRAPH); 705 706 for (var i = 0; i < subGraphs.length; i++) 707 { 708 this.importGraph(subGraphs[i], graph, node, portsMap); 709 } 710 711 //handle labels after node geometry is determined. It is also the last such that labels are on top 712 if (lblObj) 713 lbls = this.addLabels(node, lblObj, style, graph); 714 715 this.nodesMap[id] = {node: node, ports: portsMap}; 716}; 717 718mxGraphMlCodec.prototype.addNodeStyle = function (node, dataObj, style) 719{ 720 //TODO move these static mapping objects outside such that they are defined once only 721 var dashStyleFn = function(val, map) 722 { 723 if (val == "line") return; 724 725 map["dashed"] = 1; 726 //map["fixDash"] = 1; 727 var pattern = null; 728 switch(val) 729 { 730 case "DashDot": 731 pattern = "3 1 1 1"; 732 break; 733 case "Dot": 734 pattern = "1 1"; 735 break; 736 case "DashDotDot": 737 pattern = "3 1 1 1 1 1"; 738 break; 739 case "Dash": 740 pattern = "3 1"; 741 break; 742 case "dotted": 743 pattern = "1 3"; 744 break; 745 case "dashed": 746 pattern = "5 2"; 747 break; 748 default: 749 pattern = val.replace(/0/g, '1'); 750 } 751 752 if (pattern) 753 { 754 //Some patterns in graphML has only one number 755 if (pattern.indexOf(" ") < 0) 756 { 757 pattern = pattern + " " + pattern; 758 } 759 map["dashPattern"] = pattern; 760 } 761 }; 762 763 var styleCommonMap = 764 { 765 "shape": {key: "shape", mod: "shape"}, 766 "y:Shape.type": {key: "shape", mod: "shape"}, 767 "configuration": {key: "shape", mod: "shape"}, 768 "type": {key: "shape", mod: "shape"}, 769 "assetName": {key: "shape", mod: "shape"}, 770 "activityType": {key: "shape", mod: "shape"}, 771 "fill": {key: "fillColor", mod: "color"}, 772 "fill.yjs:SolidColorFill.color": {key: "fillColor", mod: "color"}, 773 "fill.yjs:SolidColorFill.color.yjs:Color.value": {key: "fillColor", mod: "color"}, 774 "y:Fill": { 775 "color": {key: "fillColor", mod: "color"}, 776 //"color2": {key: "gradientColor", mod: "color"}, //?? 777 "transparent": function(val, map) 778 { 779 if (val == "true") 780 { 781 map["fillColor"] = "none"; 782 } 783 } 784 }, 785 "y:BorderStyle": { 786 "color": {key: "strokeColor", mod: "color"}, 787 "width": "strokeWidth", 788 "hasColor": function(val, map) 789 { 790 if (val == "false") 791 { 792 map["strokeColor"] = "none"; 793 } 794 }, 795 "type": dashStyleFn 796 //"raised": ?? 797 }, 798 "stroke": {key: "strokeColor", mod: "color"}, 799 "stroke.yjs:Stroke": 800 { 801 "dashStyle": dashStyleFn, 802 "dashStyle.yjs:DashStyle.dashes": dashStyleFn, 803 "fill": {key: "strokeColor", mod: "color"}, 804 "fill.yjs:SolidColorFill.color": {key: "strokeColor", mod: "color"}, 805 //"lineCap": "", //?? 806 "thickness.sys:Double": "strokeWidth", 807 "thickness": "strokeWidth" 808 } 809 }; 810 811 var assetNodesStyle = mxUtils.clone(styleCommonMap); 812 assetNodesStyle["defaults"] = { 813 "fillColor": "#CCCCCC", 814 "strokeColor": "#6881B3" 815 }; 816 817 var bpmnActivityStyle = mxUtils.clone(styleCommonMap); 818 bpmnActivityStyle["defaults"] = { 819 "shape": "ext;rounded=1", 820 "fillColor": "#FFFFFF", 821 "strokeColor": "#000090" 822 }; 823 824 var bpmnGatewayStyle = mxUtils.clone(styleCommonMap); 825 bpmnGatewayStyle["defaults"] = { 826 "shape": "rhombus;fillColor=#FFFFFF;strokeColor=#FFCD28" 827 }; 828 829 var bpmnConversationStyle = mxUtils.clone(styleCommonMap); 830 bpmnConversationStyle["defaults"] = { 831 "shape": "hexagon", 832 "strokeColor": "#007000" 833 }; 834 835 var bpmnEventStyle = mxUtils.clone(styleCommonMap); 836 bpmnEventStyle["defaults"] = { 837 "shape": "mxgraph.bpmn.shape;perimeter=ellipsePerimeter;symbol=general", 838 "outline": "standard" 839 }; 840 bpmnEventStyle["characteristic"] = {key: "outline", mod: "bpmnOutline"}; 841 842 var bpmnDataObjectStyle = mxUtils.clone(styleCommonMap); 843 bpmnDataObjectStyle["defaults"] = { 844 "shape": "js:bpmnDataObject" 845 }; 846 847 var bpmnDataStoreStyle = mxUtils.clone(styleCommonMap); 848 bpmnDataStoreStyle["defaults"] = { 849 "shape": "datastore" 850 }; 851 852 var bpmnGroupNodeStyle = mxUtils.clone(styleCommonMap); 853 bpmnGroupNodeStyle["defaults"] = { 854 "shape": "swimlane;swimlaneLine=0;startSize=20;dashed=1;dashPattern=3 1 1 1;collapsible=0;rounded=1" 855 }; 856 857 var bpmnChoreographyNodeStyle = mxUtils.clone(styleCommonMap); 858 bpmnChoreographyNodeStyle["defaults"] = { 859 "shape": "js:BpmnChoreography"//"swimlane;childLayout=stackLayout;horizontal=1;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;startSize=20;rounded=1;collapsible=0" 860 }; 861 862 //approximation to GraphML shapes TODO improve them 863 var bevelNodeStyle = mxUtils.clone(styleCommonMap); 864 bevelNodeStyle["defaults"] = { 865 "rounded": "1", 866 "glass": "1", 867 "strokeColor": "#FFFFFF" 868 }; 869 bevelNodeStyle["inset"] = "strokeWidth"; 870 bevelNodeStyle["radius"] = "arcSize"; 871 bevelNodeStyle["drawShadow"] = {key:"shadow", mod:"bool"}; 872 bevelNodeStyle["color"] = {key:"fillColor", mod:"color", addGradient: "north"}; 873 bevelNodeStyle["color.yjs:Color.value"] = bevelNodeStyle["color"]; 874 875 var shinyPlateNodeStyle = mxUtils.clone(styleCommonMap); 876 shinyPlateNodeStyle["defaults"] = { 877 "rounded": "1", 878 "arcSize": 10, 879 "glass": "1", 880 "shadow": "1", 881 "strokeColor": "none" 882 //,"rotation": -90 //TODO requires rotation! 883 }; 884 shinyPlateNodeStyle["drawShadow"] = {key:"shadow", mod:"bool"}; 885 886 var demoGroupStyle = mxUtils.clone(styleCommonMap); 887 demoGroupStyle["defaults"] = { 888 "shape": "swimlane", 889 "startSize": 20, 890 "strokeWidth": 4, 891 "spacingLeft": 10 //TODO can we change collapse icon to be in right side? 892 }; 893 demoGroupStyle["isCollapsible"] = {key:"collapsible", mod:"bool"}; 894 demoGroupStyle["borderColor"] = {key:"strokeColor", mod:"color"}; 895 demoGroupStyle["folderFrontColor"] = {key:"fillColor", mod:"color"}; //TODO fillColor always match strokeColor! 896// demoGroupStyle["folderBackColor"] = {key:"fillColor", mod:"color"}; //?? 897 898 var collapsibleNodeStyle = mxUtils.clone(styleCommonMap); 899 collapsibleNodeStyle["defaults"] = { 900 "shape": "swimlane", 901 "startSize": 20, 902 "spacingLeft": 10 //TODO can we change collapse icon to be in right side? 903 }; 904 collapsibleNodeStyle["yjs:PanelNodeStyle"] = { 905 "color": {key:"swimlaneFillColor", mod:"color"}, 906 "color.yjs:Color.value": {key:"swimlaneFillColor", mod:"color"}, 907 "labelInsetsColor": {key:"fillColor", mod:"color"}, 908 "labelInsetsColor.yjs:Color.value": {key:"fillColor", mod:"color"} 909 }; 910 911 var tableStyle = mxUtils.clone(styleCommonMap); 912 tableStyle["defaults"] = { 913 "shape": "js:table" 914 }; 915 916 var imageNodeStyle = mxUtils.clone(styleCommonMap); 917 imageNodeStyle["defaults"] = { 918 "shape": "image" 919 }; 920 921 imageNodeStyle["image"] = function(val, map) 922 { 923 map["image"] = val; 924 }; 925 926 var svgNodeStyle = mxUtils.clone(styleCommonMap); 927 svgNodeStyle["defaults"] = { 928 "shape": "image" 929 }; 930// svgNodeStyle["y:SVGNodeProperties"] = { 931// "usingVisualBounds": ""//?? 932// }; 933// y:SVGModel.svgBoundsPolicy ?? 934 svgNodeStyle["y:SVGModel.y:SVGContent.y:Resource.#text"] = function(val, map) 935 { 936 map["image"] = "data:image/svg+xml," + ((window.btoa) ? btoa(val) : Base64.encode(val)); 937 }; 938 939 var groupNodeStyle = mxUtils.clone(styleCommonMap); 940 groupNodeStyle["defaults"] = { 941 "shape": "swimlane", 942 "startSize": 20 943 }; 944 945 groupNodeStyle["y:Shape.type"] = function(val, map) 946 { 947 if (val == "roundrectangle") 948 { 949 map['rounded'] = 1; 950 map['arcSize'] = 5; 951 } 952 }; 953 954 var tableNodeStyle = mxUtils.clone(styleCommonMap); 955 tableNodeStyle["defaults"] = { 956 "shape": "js:table2" 957 }; 958 959 var genericNodeStyle = mxUtils.clone(styleCommonMap); 960 genericNodeStyle["defaults"] = { 961 "gradientDirection": "east" 962 }; 963 genericNodeStyle["y:Fill"]["color2"] = {key: "gradientColor", mod: "color"}; 964 genericNodeStyle["y:StyleProperties.y:Property"] = { 965 "com.yworks.bpmn.characteristic": {key: "outline", mod: "bpmnOutline"}, 966 //TODO support colors for the icon itself other than the remaining shape! 967// "com.yworks.bpmn.icon.line.color": "", 968 "com.yworks.bpmn.icon.fill": {key:"gradientColor", mod:"color"}, 969 "com.yworks.bpmn.icon.fill2": {key:"fillColor", mod:"color"}, 970 "com.yworks.bpmn.type": {key: "symbol", mod: "bpmnSymbol"}, 971 "y.view.ShadowNodePainter.SHADOW_PAINTING": {key: "shadow", mod: "bool"}, 972 "doubleBorder": {key: "double", mod: "bool"}, 973 "com.yworks.sbgn.style.radius": {key: "arcSize", mod: "scale", scale: 2}, 974 "com.yworks.sbgn.style.inverse": {key: "flipV", mod: "bool"} 975 }; 976// console.log(dataObj); 977 this.mapObject(dataObj, { 978 "yjs:ShapeNodeStyle": styleCommonMap, 979 "demostyle:FlowchartNodeStyle": styleCommonMap, 980 "demostyle:AssetNodeStyle": assetNodesStyle, 981 "bpmn:ActivityNodeStyle": bpmnActivityStyle, 982 "bpmn:GatewayNodeStyle": bpmnGatewayStyle, 983 "bpmn:ConversationNodeStyle": bpmnConversationStyle, 984 "bpmn:EventNodeStyle": bpmnEventStyle, 985 "bpmn:DataObjectNodeStyle": bpmnDataObjectStyle, 986 "bpmn:DataStoreNodeStyle": bpmnDataStoreStyle, 987 "bpmn:GroupNodeStyle": bpmnGroupNodeStyle, 988 "bpmn:ChoreographyNodeStyle": bpmnChoreographyNodeStyle, 989 "yjs:BevelNodeStyle": bevelNodeStyle, 990 "yjs:ShinyPlateNodeStyle": shinyPlateNodeStyle, 991 "demostyle:DemoGroupStyle": demoGroupStyle, 992 "yjs:CollapsibleNodeStyleDecorator": collapsibleNodeStyle, 993 "bpmn:PoolNodeStyle": tableStyle, 994 "yjs:TableNodeStyle": tableStyle, 995 "demotablestyle:DemoTableStyle": tableStyle, 996 "yjs:ImageNodeStyle": imageNodeStyle, 997 //desktop 998 "y:ShapeNode": styleCommonMap, 999 "y:GenericNode": genericNodeStyle, 1000 "y:GenericGroupNode": genericNodeStyle, 1001 "y:TableNode": tableNodeStyle, 1002 "y:SVGNode": svgNodeStyle, 1003 "y:GroupNode": groupNodeStyle 1004 }, style); 1005}; 1006 1007mxGraphMlCodec.prototype.handleTemplates = function (template, userTags, node, styleMap) 1008{ 1009 if (template) 1010 { 1011 var w = node.geometry.width; 1012 var h = node.geometry.height; 1013 var header = '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 '+ w + ' ' + h +'"><g>'; 1014 var footer = '</g></svg>'; 1015 1016 //TODO optimize this! probably only the text before defs has bindings 1017 var matches = null; 1018 var bindingPairs = []; 1019 //find template bindings 1020 var tempBindRegEx = /\{TemplateBinding\s+([^}]+)\}/g; 1021 1022 while ((matches = tempBindRegEx.exec(template)) != null) 1023 { 1024 var replacement = ""; 1025 switch (matches[1]) 1026 { 1027 case "width": 1028 replacement = w; 1029 break; 1030 case "height": 1031 replacement = h; 1032 break; 1033 } 1034 1035 bindingPairs.push({match: matches[0], repl: replacement}); 1036 } 1037 1038 if (userTags && userTags["y:Json"]) 1039 { 1040 var json = JSON.parse(userTags["y:Json"]["#text"]); 1041 //find user tags bindings 1042 var userTagBindRegEx = /\{Binding\s+([^}]+)\}/g; 1043 1044 while ((matches = userTagBindRegEx.exec(template)) != null) 1045 { 1046 var parts = matches[1].split(','); 1047 var val = json[parts[0]]; 1048 1049 if (val) 1050 { 1051 if (parts.length > 1) 1052 { 1053 if (parts[1].indexOf('Converter=')) 1054 { 1055 var func = mxGraphMlConverters[parts[1].substr(11)]; //11 is the length of Converter= 1056 1057 if (func) 1058 { 1059 var args = [val]; 1060 1061 if (parts[2]) 1062 { 1063 args.push(parts[2].substr(11)); //11 is the length of Parameter= 1064 } 1065 1066 val = func.apply(null, args) 1067 } 1068 } 1069 } 1070 1071 bindingPairs.push({match: matches[0], repl: mxUtils.htmlEntities(val)}); 1072 } 1073 } 1074 } 1075 1076 for (var i = 0; i < bindingPairs.length; i++) 1077 { 1078 template = template.replace(bindingPairs[i].match, bindingPairs[i].repl); 1079 } 1080 1081 bindingPairs = []; 1082 //Fix text elements (TODO can it be merged with the previous step?) 1083 var txtRegEx = /\<text.+data-content="([^"]+).+\<\/text\>/g; 1084 while ((matches = txtRegEx.exec(template)) != null) 1085 { 1086 var val = matches[0].substr(0, matches[0].length - 7) + matches[1] + "</text>"; //7 is the length of </text> 1087 bindingPairs.push({match: matches[0], repl: val}); 1088 } 1089 1090 for (var i = 0; i < bindingPairs.length; i++) 1091 { 1092 template = template.replace(bindingPairs[i].match, bindingPairs[i].repl); 1093 } 1094 1095 var svg = header + template + footer; 1096 styleMap["shape"] = "image"; 1097 styleMap["image"] = "data:image/svg+xml," + ((window.btoa) ? btoa(svg) : Base64.encode(svg)); 1098 } 1099}; 1100 1101mxGraphMlCodec.prototype.handleCompoundShape = function (node, styleMap, mlStyleObj, lbls) 1102{ 1103 var shape = styleMap["shape"]; 1104 1105 if (shape && shape.indexOf("js:") == 0) 1106 { 1107 switch(shape) 1108 { 1109 case "js:bpmnArtifactShadow": 1110 styleMap["shadow"] = "1"; 1111 case "js:bpmnArtifact": 1112 styleMap["shape"] = styleMap["symbol"]; 1113 delete styleMap["fillColor"]; 1114 delete styleMap["strokeColor"]; 1115 delete styleMap["gradientColor"]; 1116 this.handleCompoundShape(node, styleMap, mlStyleObj, lbls) 1117 break; 1118 case "js:bpmnDataObjectShadow": 1119 case "js:bpmnDataObject": 1120 styleMap["shape"] = "note;size=16"; 1121// console.log(mlStyleObj); 1122 mlStyleObj = mlStyleObj["bpmn:DataObjectNodeStyle"] || mlStyleObj["y:GenericNode"] || mlStyleObj["y:GenericGroupNode"]; 1123 var tmpMap = {}; 1124 1125 this.mapObject(mlStyleObj, { 1126 "y:StyleProperties.y:Property": { 1127 "com.yworks.bpmn.dataObjectType": "dataObjectType", 1128 "com.yworks.bpmn.marker1": "marker1" 1129 } 1130 }, tmpMap); 1131 1132 if (mlStyleObj["collection"] == "true" || tmpMap["marker1"] == "bpmn_marker_parallel") 1133 { 1134 var cell2 = new mxCell('', new mxGeometry(0.5, 1, 10, 10), 'html=1;whiteSpace=wrap;shape=parallelMarker;'); 1135 cell2.vertex = true; 1136 cell2.geometry.relative = true; 1137 cell2.geometry.offset = new mxPoint(-5, -10); 1138 node.insert(cell2); 1139 } 1140 if (mlStyleObj["type"] == "INPUT" || tmpMap["dataObjectType"] == "data_object_type_input") 1141 { 1142 var cell1 = new mxCell('', new mxGeometry(0, 0, 10, 10), 'html=1;shape=singleArrow;arrowWidth=0.4;arrowSize=0.4;'); 1143 cell1.vertex = true; 1144 cell1.geometry.relative = true; 1145 cell1.geometry.offset = new mxPoint(2, 2); 1146 node.insert(cell1); 1147 } 1148 else if (mlStyleObj["type"] == "OUTPUT" || tmpMap["dataObjectType"] == "data_object_type_output") 1149 { 1150 var cell1 = new mxCell('', new mxGeometry(0, 0, 10, 10), 'html=1;shape=singleArrow;arrowWidth=0.4;arrowSize=0.4;fillColor=#000000;'); 1151 cell1.vertex = true; 1152 cell1.geometry.relative = true; 1153 cell1.geometry.offset = new mxPoint(2, 2); 1154 node.insert(cell1); 1155 } 1156 break; 1157 case "js:BpmnChoreography": 1158 this.mapObject(mlStyleObj, { 1159 "defaults": { 1160 "shape": "swimlane;collapsible=0;rounded=1", 1161 "startSize": "20", 1162 "strokeColor": "#006000", 1163 "fillColor": "#CCCCCC" 1164 } 1165 }, styleMap); 1166 1167 //TODO the shape should be clipped by parent borders. It should also be resized relative to its parent 1168 var pGeo = node.geometry; 1169 var cell1 = new mxCell('', new mxGeometry(0, pGeo.height - 20, pGeo.width, 20), 'strokeColor=#006000;fillColor=#777777;rounded=1'); 1170 cell1.vertex = true; 1171 node.insert(cell1); 1172 1173 //TODO handle labels accurately 1174 if (lbls && lbls.lblTxts) 1175 { 1176// console.log(lbls); 1177 node.value = lbls.lblTxts[0]; 1178 cell1.value = lbls.lblTxts[1]; 1179 } 1180 break; 1181 case "js:bpmnActivityShadow": 1182 case "js:bpmnActivity": 1183 styleMap["shape"] = "ext;rounded=1"; 1184 var tmpMap = {}; 1185 mlStyleObj = mlStyleObj["y:GenericNode"] || mlStyleObj["y:GenericGroupNode"]; 1186 1187 this.mapObject(mlStyleObj, { 1188 "y:StyleProperties.y:Property": { 1189 "com.yworks.bpmn.taskType": "taskType", 1190 "com.yworks.bpmn.activityType": "activityType", 1191 "com.yworks.bpmn.marker1": "marker1", 1192 "com.yworks.bpmn.marker2": "marker2", 1193 "com.yworks.bpmn.marker3": "marker3", 1194 "com.yworks.bpmn.marker4": "marker4" 1195 } 1196 }, tmpMap); 1197 1198 switch(tmpMap["activityType"]) 1199 { 1200 case "activity_type_transaction": 1201 styleMap["double"] = "1"; 1202 break; 1203 } 1204 1205 switch(tmpMap["taskType"]) 1206 { 1207 case "task_type_send": 1208 var item1 = new mxCell('', new mxGeometry(0, 0, 19, 12), 'shape=message;fillColor=#000000;strokeColor=#FFFFFF;'); 1209 item1.geometry.offset = new mxPoint(4, 7); 1210 break; 1211 case "task_type_receive": 1212 var item1 = new mxCell('', new mxGeometry(0, 0, 19, 12), 'shape=message;'); 1213 item1.geometry.offset = new mxPoint(4, 7); 1214 break; 1215 case "task_type_user": 1216 var item1 = new mxCell('', new mxGeometry(0, 0, 15, 15), 'shape=mxgraph.bpmn.user_task;'); 1217 item1.geometry.offset = new mxPoint(4, 5); 1218 break; 1219 case "task_type_manual": 1220 var item1 = new mxCell('', new mxGeometry(0, 0, 15, 10), 'shape=mxgraph.bpmn.manual_task;'); 1221 item1.geometry.offset = new mxPoint(4, 7); 1222 break; 1223 case "task_type_business_rule": 1224 var item1 = new mxCell('', new mxGeometry(0, 0, 18, 13), 'shape=mxgraph.bpmn.business_rule_task;'); 1225 item1.geometry.offset = new mxPoint(4, 7); 1226 break; 1227 case "task_type_service": 1228 var item1 = new mxCell('', new mxGeometry(0, 0, 15, 15), 'shape=mxgraph.bpmn.service_task;'); 1229 item1.geometry.offset = new mxPoint(4, 5); 1230 break; 1231 case "task_type_script": 1232 var item1 = new mxCell('', new mxGeometry(0, 0, 15, 15), 'shape=mxgraph.bpmn.script_task;'); 1233 item1.geometry.offset = new mxPoint(4, 5); 1234 break; 1235 } 1236 1237 if (item1) 1238 { 1239 item1.vertex = true; 1240 item1.geometry.relative = true; 1241 node.insert(item1); 1242 item1 = null; 1243 } 1244 1245 var numIcons = 0; 1246 1247 for (var i = 1; i <= 4; i++) 1248 { 1249 if (tmpMap["marker" + i]) 1250 numIcons++; 1251 } 1252 1253 var iconX = -7.5 * numIcons - 2 * (numIcons - 1); 1254 1255 for (var i = 1; i <= numIcons; i++) 1256 { 1257 switch(tmpMap["marker" + i]) 1258 { 1259 case "bpmn_marker_closed": 1260 var item1 = new mxCell('', new mxGeometry(0.5, 1, 15, 15), 'shape=plus;part=1;'); 1261 item1.geometry.offset = new mxPoint(iconX, -20); 1262 break; 1263 case "bpmn_marker_open": 1264 var item1 = new mxCell('', new mxGeometry(0.5, 1, 15, 15), 'shape=rect;part=1;'); 1265 item1.geometry.offset = new mxPoint(iconX, -20); 1266 var item2 = new mxCell('', new mxGeometry(0.5, 0.5, 8, 1), 'shape=rect;part=1;'); 1267 item2.geometry.offset = new mxPoint(-4, -1); 1268 item2.geometry.relative = true; 1269 item2.vertex = true; 1270 item1.insert(item2); 1271 break; 1272 case "bpmn_marker_loop": 1273 var item1 = new mxCell('', new mxGeometry(0.5, 1, 15, 15), 'shape=mxgraph.bpmn.loop;part=1;'); 1274 item1.geometry.offset = new mxPoint(iconX, -20); 1275 break; 1276 case "bpmn_marker_parallel": 1277 var item1 = new mxCell('', new mxGeometry(0.5, 1, 15, 15), 'shape=parallelMarker;part=1;'); 1278 item1.geometry.offset = new mxPoint(iconX, -20); 1279 break; 1280 case "bpmn_marker_sequential": 1281 var item1 = new mxCell('', new mxGeometry(0.5, 1, 15, 15), 'shape=parallelMarker;direction=south;part=1;'); 1282 item1.geometry.offset = new mxPoint(iconX, -20); 1283 break; 1284 case "bpmn_marker_ad_hoc": 1285 var item1 = new mxCell('', new mxGeometry(0.5, 1, 15, 10), 'shape=mxgraph.bpmn.ad_hoc;strokeColor=none;flipH=1;part=1;fillColor=#000000'); 1286 item1.geometry.offset = new mxPoint(iconX, -17); 1287 break; 1288 case "bpmn_marker_compensation": 1289 var item1 = new mxCell('', new mxGeometry(0.5, 1, 15, 11), 'shape=mxgraph.bpmn.compensation;part=1;'); 1290 item1.geometry.offset = new mxPoint(iconX, -18); 1291 break; 1292 } 1293 item1.geometry.relative = true; 1294 item1.vertex = true; 1295 node.insert(item1); 1296 iconX += 20; 1297 } 1298 break; 1299 case "js:table": 1300 //TODO we need 2 passes to find the exact shift of columns/rows especially when there is rows inside rows 1301 //TODO Internal table strokes needs to match table strokeWidth and only be on one side 1302 //TODO code optimization 1303 styleMap["shape"] = "swimlane;collapsible=0;swimlaneLine=0"; 1304 var tableObj = mlStyleObj["yjs:TableNodeStyle"] || mlStyleObj["demotablestyle:DemoTableStyle"]; 1305 1306 if (!tableObj && mlStyleObj["bpmn:PoolNodeStyle"]) 1307 { 1308 tableObj = mlStyleObj["bpmn:PoolNodeStyle"]["yjs:TableNodeStyle"]; 1309 } 1310 1311// console.log(tableObj); 1312 1313 this.mapObject(tableObj, { 1314 "backgroundStyle.demotablestyle:TableBackgroundStyle": { 1315 "insetFill.yjs:SolidColorFill.color.yjs:Color.value": {key: "fillColor", mod: "color"}, 1316 "tableBackgroundFill.yjs:SolidColorFill.color.yjs:Color.value": {key: "swimlaneFillColor", mod: "color"}, 1317 "tableBackgroundStroke.yjs:Stroke":{ 1318 "fill": {key: "strokeColor", mod: "color"}, 1319 "thickness": "strokeWidth" 1320 } 1321 }, 1322 "backgroundStyle.yjs:ShapeNodeStyle.fill": {key: "fillColor", mod: "color"}, 1323 "backgroundStyle.yjs:ShapeNodeStyle.fill.yjs:SolidColorFill.color": {key: "fillColor", mod: "color"} 1324 }, styleMap); 1325 1326 //Lane fill color is the same as the fill color 1327 styleMap["swimlaneFillColor"] = styleMap["fillColor"]; 1328 1329 tableObj = tableObj["table"]["y:Table"]; 1330 1331 var x = 0, y = 0, xShift = {x: 0}, yShift = 0; 1332 var insets = tableObj["Insets"]; 1333 1334 if (insets) 1335 { 1336 insets = insets.split(','); 1337 1338 if (insets[0] != "0") 1339 { 1340 styleMap["startSize"] = insets[0]; 1341 xShift.x = parseFloat(insets[0]); 1342 //x += xShift.x; 1343 styleMap["horizontal"] = "0"; 1344 } 1345 else if (insets[1] != "0") 1346 { 1347 styleMap["startSize"] = insets[1]; 1348 yShift = parseFloat(insets[1]); 1349 y += yShift; 1350 } 1351 } 1352 else 1353 { 1354 styleMap["startSize"] = "0"; 1355 } 1356 1357 var defRowStyle = {}; 1358 1359 var rowMapping = { 1360 "Insets": function(val, map) 1361 { 1362 map["startSize"] = val.split(',')[0]; 1363 }, 1364 "Style.bpmn:AlternatingLeafStripeStyle": { 1365 "evenLeafDescriptor.bpmn:StripeDescriptor": { 1366 "insetFill": {key: "evenFill", mod: "color"}, 1367 "backgroundFill": {key: "evenLaneFill", mod: "color"} 1368 }, 1369 "oddLeafDescriptor.bpmn:StripeDescriptor": { 1370 "insetFill": {key: "oddFill", mod: "color"}, 1371 "backgroundFill": {key: "oddLaneFill", mod: "color"} 1372 } 1373 //parentDescriptor ?? 1374 //TODO collect common types in a special mapping hash 1375 }, 1376 "Style.yjs:NodeStyleStripeStyleAdapter":{ 1377 "demotablestyle:DemoStripeStyle": { 1378 "stripeInsetFill.yjs:SolidColorFill.color.yjs:Color.value": {key: "fillColor", mod: "color"}, 1379 "tableLineFill.yjs:SolidColorFill.color.yjs:Color.value": {key: "strokeColor", mod: "color"} 1380 }, 1381 "yjs:ShapeNodeStyle": { 1382 "fill": {key: "swimlaneFillColor", mod: "color"} 1383 } 1384 }, 1385 "Size": "height" 1386 }; 1387 this.mapObject(tableObj["RowDefaults"], { 1388 "defaults": { 1389 "shape": "swimlane;collapsible=0;horizontal=0", 1390 "startSize": "0" 1391 }, 1392 "y:StripeDefaults": rowMapping 1393 }, defRowStyle); 1394 1395 var defColStyle = {}; 1396 1397 var colMapping = { 1398 "Insets": function(val, map) 1399 { 1400 map["startSize"] = val.split(',')[1]; 1401 }, 1402 "Style.bpmn:AlternatingLeafStripeStyle": { 1403 "evenLeafDescriptor.bpmn:StripeDescriptor": { 1404 "insetFill": {key: "evenFill", mod: "color"}, 1405 "backgroundFill": {key: "evenLaneFill", mod: "color"} 1406 }, 1407 "oddLeafDescriptor.bpmn:StripeDescriptor": { 1408 "insetFill": {key: "oddFill", mod: "color"}, 1409 "backgroundFill": {key: "oddLaneFill", mod: "color"} 1410 } 1411 //parentDescriptor ?? 1412 //TODO collect common types in a special mapping hash 1413 }, 1414 "Style.yjs:NodeStyleStripeStyleAdapter":{ 1415 "demotablestyle:DemoStripeStyle": { 1416 "stripeInsetFill.yjs:SolidColorFill.color.yjs:Color.value": {key: "fillColor", mod: "color"}, 1417 "tableLineFill.yjs:SolidColorFill.color.yjs:Color.value": {key: "strokeColor", mod: "color"} 1418 }, 1419 "yjs:ShapeNodeStyle": { 1420 "fill": {key: "swimlaneFillColor", mod: "color"} 1421 } 1422 }, 1423 "Size": "width" 1424 }; 1425 1426 this.mapObject(tableObj["ColumnDefaults"], { 1427 "defaults": { 1428 "shape": "swimlane;collapsible=0", 1429 "startSize": "0", 1430 "fillColor": "none" 1431 }, 1432 "y:StripeDefaults": colMapping 1433 }, defColStyle); 1434 1435 var pGeo = node.geometry; 1436 1437 var rows = tableObj["Rows"]["y:Row"]; 1438 y += parseFloat(defColStyle["startSize"]); 1439 1440 var maxX = xShift.x; 1441 var initX = xShift.x; 1442 xShift.lx = xShift.x; 1443 1444 //TODO We need two passes to determine the header size! 1445 if (rows) 1446 { 1447 if (!(rows instanceof Array)) 1448 rows = [rows]; 1449 1450 for (var i = 0; i < rows.length; i++) 1451 { 1452 xShift.x = initX; 1453 xShift.lx = initX; 1454 y = this.addRow(rows[i], node, (i & 1), y, xShift, rowMapping, defRowStyle); 1455 maxX = Math.max(xShift.x, maxX); 1456 } 1457 } 1458 1459 var columns = tableObj["Columns"]["y:Column"]; 1460 x = maxX;//parseFloat(defRowStyle["startSize"]); 1461 1462 if (columns) 1463 { 1464 if (!(columns instanceof Array)) 1465 columns = [columns]; 1466 1467 for (var i = 0; i < columns.length; i++) 1468 { 1469 x = this.addColumn(columns[i], node, (i & 1), x, yShift, colMapping, defColStyle); 1470 } 1471 } 1472 1473 break; 1474 case "js:table2": 1475 styleMap["shape"] = "swimlane;collapsible=0;swimlaneLine=0"; 1476// console.log(mlStyleObj); 1477 var tmpMap = {}; 1478 this.mapObject(mlStyleObj, { 1479 "y:TableNode": { 1480 "y:StyleProperties.y:Property": { 1481 "yed.table.section.color": {key: "secColor", mod: "color"}, 1482 "yed.table.header.height": "headerH", 1483 "yed.table.header.color.main": {key: "headerColor", mod: "color"}, 1484 "yed.table.header.color.alternating": {key: "headerColorAlt", mod: "color"}, 1485 "yed.table.lane.color.main": {key: "laneColor", mod: "color"}, 1486 "yed.table.lane.color.alternating": {key: "laneColorAlt", mod: "color"}, 1487 "yed.table.lane.style": "laneStyle", 1488 "com.yworks.bpmn.type": "isHorz", 1489 "POOL_LANE_COLOR_ALTERNATING": {key: "laneColorAlt", mod: "color"}, 1490 "POOL_LANE_COLOR_MAIN": {key: "laneColor", mod: "color"}, 1491 "POOL_LANE_STYLE": "laneStyle", 1492 "POOL_HEADER_COLOR_MAIN": {key: "headerColor", mod: "color"}, 1493 "POOL_HEADER_COLOR_ALTERNATING": {key: "headerColorAlt", mod: "color"}, 1494 "POOL_TABLE_SECTION_COLOR": {key: "secColor", mod: "color"} 1495// //Not Used! 1496// "y.view.tabular.TableNodePainter.ALTERNATE_ROW_STYLE": { 1497// "y:SimpleStyle": { 1498// "fillColor": {key: "rowAltFillColor", mod: "color"}, 1499// "lineColor": {key: "rowAltLineColor", mod: "color"}, 1500// "lineType": "rowAltlineType", 1501// "lineWidth": "rowAltlineWidth" 1502// } 1503// }, 1504// "y.view.tabular.TableNodePainter.ALTERNATE_COLUMN_STYLE": { 1505// "y:SimpleStyle": { 1506// "fillColor": {key: "colAltFillColor", mod: "color"}, 1507// "lineColor": {key: "colAltLineColor", mod: "color"}, 1508// "lineType": "colAltlineType", 1509// "lineWidth": "colAltlineWidth" 1510// } 1511// } 1512 }, 1513 "y:Table": { 1514 "y:DefaultColumnInsets.top": "colHHeight", 1515 "y:DefaultRowInsets.left": "rowHWidth", 1516 "y:Insets": { 1517 "top": "tblHHeight", 1518 "left": "tblHWidth" 1519 } 1520 } 1521 } 1522 }, tmpMap); 1523 1524 styleMap["swimlaneFillColor"] = styleMap["fillColor"]; 1525 1526 var isHor = tmpMap["isHorz"] == "pool_type_lane_and_column" 1527 || tmpMap["isHorz"] == "pool_type_empty" 1528 || tmpMap["isHorz"] == "pool_type_lane"; 1529 1530 var th = 0, tw = 0; 1531 if (isHor) 1532 { 1533 tw = parseFloat(tmpMap["tblHWidth"]); 1534 } 1535 else 1536 { 1537 th = parseFloat(tmpMap["tblHHeight"]); 1538 } 1539 1540 styleMap["startSize"] = th? th : tw; 1541 //Assumptions: There is always rows and cols in every table 1542 //Also all tables seems to be not rotated 1543 try 1544 { 1545 var rows = mlStyleObj["y:TableNode"]["y:Table"]["y:Rows"]["y:Row"]; 1546 var cols = mlStyleObj["y:TableNode"]["y:Table"]["y:Columns"]["y:Column"]; 1547 1548 var atts4Rows = tmpMap["laneStyle"] == "lane.style.rows" || tmpMap["laneStyle"] == "lane_style_rows"; 1549 1550 if (!(rows instanceof Array)) 1551 rows = [rows]; 1552 1553 if (!(cols instanceof Array)) 1554 cols = [cols]; 1555 1556 var rowStartSize = parseFloat(tmpMap["rowHWidth"]); 1557 for (var i = 0; i < rows.length; i++) 1558 { 1559 if (rows[i]["y:Insets"]) 1560 rowStartSize = Math.max(rowStartSize, 1561 parseFloat(rows[i]["y:Insets"]["left"]) + parseFloat(rows[i]["y:Insets"]["right"])); 1562 } 1563 1564 var colStartSize = parseFloat(tmpMap["colHHeight"]); 1565 for (var i = 0; i < cols.length; i++) 1566 { 1567 if (cols[i]["y:Insets"]) 1568 colStartSize = Math.max(colStartSize, 1569 parseFloat(cols[i]["y:Insets"]["top"]) + parseFloat(cols[i]["y:Insets"]["bottom"])); 1570 } 1571 1572 if (atts4Rows) 1573 { 1574 this.addTbl2Rows(node, rows, th, tw, rowStartSize, colStartSize, atts4Rows, tmpMap); 1575 this.addTbl2Cols(node, cols, th, tw, rowStartSize, colStartSize, atts4Rows, tmpMap); 1576 } 1577 else 1578 { 1579 this.addTbl2Cols(node, cols, th, tw, rowStartSize, colStartSize, atts4Rows, tmpMap); 1580 this.addTbl2Rows(node, rows, th, tw, rowStartSize, colStartSize, atts4Rows, tmpMap); 1581 } 1582 } 1583 catch(e) 1584 { 1585 //nothing! 1586 } 1587 break; 1588 case "js:relationship_big_entity": 1589 styleMap['shape'] = "swimlane;startSize=30;rounded=1;arcSize=5;collapsible=0"; 1590 var fill = mlStyleObj["y:GenericNode"]["y:Fill"]; 1591 1592 if (fill) 1593 { 1594 styleMap['fillColor'] = fill["color2"]; 1595 styleMap['swimlaneFillColor'] = fill["color"]; 1596 } 1597 break; 1598 case "js:relationship_attribute": 1599 if (styleMap["double"] == "1") 1600 { 1601 styleMap['shape'] = "doubleEllipse"; 1602 } 1603 else 1604 { 1605 styleMap['shape'] = "ellipse"; 1606 } 1607 break; 1608 } 1609 1610 if (shape.indexOf("Shadow") > 0) 1611 { 1612 styleMap["shadow"] = "1"; 1613 } 1614 } 1615}; 1616 1617mxGraphMlCodec.prototype.addTbl2Rows = function(node, rows, th, tw, rowStartSize, colStartSize, atts4Rows, tmpMap) 1618{ 1619 var y = th + colStartSize; 1620 var isBPMN = tmpMap["isHorz"] != null; 1621 1622 for (var i = 0; i < rows.length; i++) 1623 { 1624 var odd = i & 1; 1625 var cell = new mxCell(); 1626 cell.vertex = true; 1627 var rowStyle = { 1628 "shape": "swimlane;collapsible=0;horizontal=0", 1629 "startSize": rowStartSize, 1630 "fillColor": tmpMap["secColor"] || "none", 1631 "swimlaneLine": (isBPMN? "0" : "1") 1632 }; 1633 1634 if (parseFloat(rowStyle["startSize"]) == 0) 1635 { 1636 rowStyle["fillColor"] = "none"; 1637 rowStyle["swimlaneLine"] = "0"; 1638 } 1639 1640 if (atts4Rows) 1641 { 1642 var fillColor = odd? tmpMap["headerColorAlt"] : tmpMap["headerColor"]; 1643 rowStyle["swimlaneFillColor"] = odd? tmpMap["laneColorAlt"] : tmpMap["laneColor"]; 1644 rowStyle["fillColor"] = fillColor? fillColor : rowStyle["swimlaneFillColor"]; 1645 } 1646 1647 var height = parseFloat(rows[i]["height"]); 1648 var dh = (isBPMN && i == 0)? colStartSize : 0 ; 1649 cell.geometry = new mxGeometry(tw, y - dh, node.geometry.width - tw, height + dh); 1650 y += height; 1651 1652// if (lblObj) 1653// this.addLabels(cell, lblObj, rowStyle) 1654 1655 cell.style = this.styleMap2Str(rowStyle); 1656 node.insert(cell); 1657 } 1658}; 1659 1660mxGraphMlCodec.prototype.addTbl2Cols = function(node, cols, th, tw, rowStartSize, colStartSize, atts4Rows, tmpMap) 1661{ 1662 var x = rowStartSize + tw; 1663 var isBPMN = tmpMap["isHorz"] != null; 1664 1665 for (var i = 0; i < cols.length; i++) 1666 { 1667 var odd = i & 1; 1668 var cell = new mxCell(); 1669 cell.vertex = true; 1670 var colStyle = { 1671 "shape": "swimlane;collapsible=0", 1672 "startSize": colStartSize, 1673 "fillColor": tmpMap["secColor"] || "none", 1674 "swimlaneLine": (isBPMN? "0" : "1") 1675 }; 1676 1677 if (parseFloat(colStyle["startSize"]) == 0) 1678 { 1679 colStyle["fillColor"] = "none"; 1680 } 1681 1682 if (!atts4Rows) 1683 { 1684 var fillColor = odd? tmpMap["headerColorAlt"] : tmpMap["headerColor"]; 1685 colStyle["swimlaneFillColor"] = odd? tmpMap["laneColorAlt"] : tmpMap["laneColor"]; 1686 colStyle["fillColor"] = fillColor? fillColor : colStyle["swimlaneFillColor"]; 1687 } 1688 1689 var width = parseFloat(cols[i]["width"]); 1690 var dw = (isBPMN && i == 0)? rowStartSize : 0 ; 1691 cell.geometry = new mxGeometry(x - dw, th, width + dw, node.geometry.height - th); 1692 x += width; 1693 1694// if (lblObj) 1695// this.addLabels(cell, lblObj, rowStyle) 1696 1697 cell.style = this.styleMap2Str(colStyle); 1698 node.insert(cell); 1699 } 1700}; 1701 1702mxGraphMlCodec.prototype.addRow = function(row, parent, odd, y, xShift, rowMapping, defRowStyle) 1703{ 1704 var cell = new mxCell(); 1705 cell.vertex = true; 1706 var rowStyle = mxUtils.clone(defRowStyle); 1707 this.mapObject(row, rowMapping, rowStyle); 1708 1709 if (odd) 1710 { 1711 if (rowStyle["oddFill"]) 1712 rowStyle["fillColor"] = rowStyle["oddFill"]; 1713 1714 if (rowStyle["oddLaneFill"]) 1715 rowStyle["swimlaneFillColor"] = rowStyle["oddLaneFill"]; 1716 } 1717 else 1718 { 1719 if (rowStyle["evenFill"]) 1720 rowStyle["fillColor"] = rowStyle["evenFill"]; 1721 1722 if (rowStyle["evenLaneFill"]) 1723 rowStyle["swimlaneFillColor"] = rowStyle["evenLaneFill"]; 1724 } 1725 1726 var height = parseFloat(rowStyle["height"]); 1727 cell.geometry = new mxGeometry(xShift.lx, y, parent.geometry.width - xShift.lx, height); 1728 1729 var lblObj = row["Labels"]; 1730 1731 if (lblObj) 1732 this.addLabels(cell, lblObj, rowStyle) 1733 1734 cell.style = this.styleMap2Str(rowStyle); 1735 parent.insert(cell); 1736 1737 var subRow = row["y:Row"]; 1738 1739 xShift.lx = 0; 1740 if (rowStyle["startSize"]) 1741 { 1742 xShift.lx = parseFloat(rowStyle["startSize"]); 1743 xShift.x += xShift.lx; 1744 } 1745 1746 var initX = xShift.x, maxX = xShift.x, initLx = xShift.lx; 1747 var subY = 0; 1748 if (subRow) 1749 { 1750 if (!(subRow instanceof Array)) 1751 subRow = [subRow]; 1752 1753 for (var i = 0; i < subRow.length; i++) 1754 { 1755 xShift.x = initX; 1756 xShift.lx = initLx; 1757 subY = this.addRow(subRow[i], cell, (i & 1), subY, xShift, rowMapping, defRowStyle); 1758 maxX = Math.max(xShift.x, maxX) 1759 } 1760 } 1761 xShift.x = maxX; 1762 height = Math.max(height, subY); 1763 cell.geometry.height = height; 1764 y += height; 1765 1766 return y; 1767} 1768 1769mxGraphMlCodec.prototype.addColumn = function(column, parent, odd, x, yShift, colMapping, defColStyle) 1770{ 1771 var cell = new mxCell(); 1772 cell.vertex = true; 1773 var colStyle = mxUtils.clone(defColStyle); 1774 this.mapObject(column, colMapping, colStyle); 1775 1776 if (odd) 1777 { 1778 if (colStyle["oddFill"]) 1779 colStyle["fillColor"] = colStyle["oddFill"]; 1780 1781 if (colStyle["oddLaneFill"]) 1782 colStyle["swimlaneFillColor"] = colStyle["oddLaneFill"]; 1783 } 1784 else 1785 { 1786 if (colStyle["evenFill"]) 1787 colStyle["fillColor"] = colStyle["evenFill"]; 1788 1789 if (colStyle["evenLaneFill"]) 1790 colStyle["swimlaneFillColor"] = colStyle["evenLaneFill"]; 1791 } 1792 1793 var width = parseFloat(colStyle["width"]); 1794 cell.geometry = new mxGeometry(x, yShift, width, parent.geometry.height - yShift); 1795 1796 var lblObj = column["Labels"]; 1797 1798 if (lblObj) 1799 this.addLabels(cell, lblObj, colStyle) 1800 1801 cell.style = this.styleMap2Str(colStyle); 1802 parent.insert(cell); 1803 1804 var subCol = column["y:Column"]; 1805 1806 var subX = 0; 1807 if (subCol) 1808 { 1809 if (!(subCol instanceof Array)) 1810 subCol = [subCol]; 1811 1812 for (var i = 0; i < subCol.length; i++) 1813 { 1814 subX = this.addColumn(subCol[i], cell, (i & 1), subX, yShift, colMapping, defColStyle); 1815 } 1816 } 1817 width = Math.max(width, subX); 1818 cell.geometry.width = width; 1819 x += width; 1820 return x; 1821} 1822 1823mxGraphMlCodec.prototype.handleFixedRatio = function (node, styleMap) 1824{ 1825 var shape = styleMap["shape"]; 1826 var geo = node.geometry; 1827 1828 if (shape && geo) 1829 { 1830 if (shape.indexOf(";aspect=fixed") > 0) 1831 { 1832 1833 var min = Math.min(geo.height, geo.width); 1834 1835 if (min == geo.height) //fix coordinates 1836 { 1837 geo.x += (geo.width - min) / 2; 1838 } 1839 1840 geo.height = min; 1841 geo.width = min; 1842 } 1843 else if (shape.indexOf(";rotation=90") > 0 || shape.indexOf(";rotation=-90") > 0 ) 1844 { 1845 var h = geo.height; 1846 var w = geo.width; 1847 geo.height = w; 1848 geo.width = h; 1849 var diff = (h - w) / 2; 1850 geo.x -= diff; 1851 geo.y += diff; 1852 } 1853 } 1854}; 1855 1856mxGraphMlCodec.prototype.addNodeGeo = function (node, geoObj, dx, dy) 1857{ 1858 var geoRect = geoObj[mxGraphMlConstants.RECT]; 1859 1860 var x = 0, y = 0, w = 30, h = 30; //some node has no geometry, this is the default 1861 if (geoRect) 1862 { 1863 x = geoRect[mxGraphMlConstants.X]; 1864 y = geoRect[mxGraphMlConstants.Y]; 1865 w = geoRect[mxGraphMlConstants.WIDTH]; 1866 h = geoRect[mxGraphMlConstants.HEIGHT]; 1867 } 1868 else 1869 { 1870 x = geoObj[mxGraphMlConstants.X_L] || x; 1871 y = geoObj[mxGraphMlConstants.Y_L] || y; 1872 w = geoObj[mxGraphMlConstants.WIDTH_L] || w; 1873 h = geoObj[mxGraphMlConstants.HEIGHT_L] || h; 1874 } 1875 1876 var geo = node.geometry; 1877 geo.x = parseFloat(x) - dx; 1878 geo.y = parseFloat(y) - dy; 1879 geo.width = parseFloat(w); 1880 geo.height = parseFloat(h); 1881}; 1882 1883//TODO handle other ports cases 1884mxGraphMlCodec.prototype.importEdge = function (edgeElement, graph, parent, dx, dy) 1885{ 1886 var data = this.getDirectChildNamedElements(edgeElement, mxGraphMlConstants.DATA); 1887 var e; 1888 var id = edgeElement.getAttribute(mxGraphMlConstants.ID); 1889 var srcId = edgeElement.getAttribute(mxGraphMlConstants.EDGE_SOURCE); 1890 var trgId = edgeElement.getAttribute(mxGraphMlConstants.EDGE_TARGET); 1891 var srcPortId = edgeElement.getAttribute(mxGraphMlConstants.EDGE_SOURCE_PORT); 1892 var trgPortId = edgeElement.getAttribute(mxGraphMlConstants.EDGE_TARGET_PORT); 1893 1894 var src = this.nodesMap[srcId]; 1895 var trg = this.nodesMap[trgId]; 1896 1897 var edge = graph.insertEdge(parent, null, "", src.node, trg.node, "graphMLId=" + id); 1898 var style = {graphMlID: id}; 1899 1900 for (var i = 0; i < data.length; i++) 1901 { 1902 var d = data[i]; 1903 var dataObj = this.dataElem2Obj(d); 1904 var desktopEdgeObj = dataObj["y:PolyLineEdge"] || dataObj["y:GenericEdge"] || 1905 dataObj["y:ArcEdge"] || dataObj["y:BezierEdge"] || 1906 dataObj["y:QuadCurveEdge"] || dataObj["y:SplineEdge"]; 1907 1908 if (dataObj.key == this.edgesKeys[mxGraphMlConstants.EDGE_GEOMETRY].key) 1909 { 1910 this.addEdgeGeo(edge, dataObj, dx, dy); 1911 } 1912 else if (dataObj.key == this.edgesKeys[mxGraphMlConstants.EDGE_STYLE].key) 1913 { 1914// console.log(dataObj); 1915 this.addEdgeStyle(edge, dataObj, style); 1916 } 1917 else if (dataObj.key == this.edgesKeys[mxGraphMlConstants.EDGE_LABELS].key) 1918 { 1919 this.addLabels(edge, dataObj, style, graph); 1920 } 1921 else if (desktopEdgeObj) 1922 { 1923 this.addEdgeStyle(edge, dataObj, style); 1924 var absPoints = this.addEdgePath(edge, desktopEdgeObj["y:Path"], style, dx, dy); 1925 1926 if (desktopEdgeObj["y:EdgeLabel"]) 1927 this.addLabels(edge, desktopEdgeObj["y:EdgeLabel"], style, graph, absPoints); 1928 1929 //special case for link edge 1930 //TODO link doesn't support arrow head types 1931 if (style["shape"] != null && style["shape"].indexOf("link") == 0) 1932 { 1933 style["width"] = style["strokeWidth"]; 1934 style["strokeWidth"] = 1; 1935 } 1936 } 1937 } 1938 1939 //handle simple ports (exit/entry[X/Y]) 1940 if (src.ports && srcPortId) 1941 { 1942 var srcPort = src.ports[srcPortId]; 1943 1944 if (srcPort.pos) 1945 { 1946 style["exitX"] = srcPort.pos.x; 1947 style["exitY"] = srcPort.pos.y; 1948 } 1949 } 1950 1951 if (trg.ports && trgPortId) 1952 { 1953 var trgPort = trg.ports[trgPortId]; 1954 1955 if (trgPort.pos) 1956 { 1957 style["entryX"] = trgPort.pos.x; 1958 style["entryY"] = trgPort.pos.y; 1959 } 1960 } 1961 1962 edge.style = this.styleMap2Str(style); 1963 1964 return edge; 1965}; 1966 1967mxGraphMlCodec.prototype.addEdgeGeo = function (edge, geoObj, dx, dy) 1968{ 1969 var list = geoObj[mxGraphMlConstants.Y_BEND]; 1970 1971 if (list) 1972 { 1973 var points = []; 1974 1975 for (var i = 0; i < list.length; i++) { 1976 var pointStr = list[i][mxGraphMlConstants.LOCATION]; 1977 1978 if (pointStr) { 1979 var xy = pointStr.split(','); 1980 points.push(new mxPoint(parseFloat(xy[0]) - dx, parseFloat(xy[1]) - dy)); 1981 } 1982 } 1983 1984 edge.geometry.points = points; 1985 } 1986}; 1987 1988mxGraphMlCodec.prototype.addEdgePath = function (edge, pathObj, style, dx, dy) 1989{ 1990 var absPoints = []; 1991 if (pathObj) 1992 { 1993 var srcX = parseFloat(pathObj.sx), srcY = parseFloat(pathObj.sy), 1994 trgX = parseFloat(pathObj.tx), trgY = parseFloat(pathObj.ty); 1995 1996 var srcGeo = edge.source.geometry; 1997 if (srcX != 0 || srcY != 0) 1998 { 1999 style["exitX"] = (srcX + srcGeo.width/2) / srcGeo.width; 2000 style["exitY"] = (srcY + srcGeo.height/2) / srcGeo.height; 2001 absPoints.push(new mxPoint(srcGeo.x + style["exitX"] * srcGeo.width - dx, srcGeo.y + style["exitY"] * srcGeo.height - dy)); 2002 } 2003 else 2004 { 2005 absPoints.push(new mxPoint(srcGeo.x + srcGeo.width/2 - dx, srcGeo.y + srcGeo.height/2 - dy)); 2006 } 2007 2008 var endP = null; 2009 var trgGeo = edge.target.geometry; 2010 if (trgX != 0 || trgY != 0) 2011 { 2012 style["entryX"] = (trgX + trgGeo.width/2) / trgGeo.width; 2013 style["entryY"] = (trgY + trgGeo.height/2) / trgGeo.height; 2014 endP = new mxPoint(trgGeo.x + style["entryX"] * trgGeo.width - dx, trgGeo.y + style["entryY"] * trgGeo.height - dy); 2015 } 2016 else 2017 { 2018 endP = new mxPoint(trgGeo.x + trgGeo.width/2 - dx, trgGeo.y + trgGeo.height/2 - dy); 2019 } 2020 2021 var list = pathObj["y:Point"]; 2022 2023 if (list) 2024 { 2025 if (!(list instanceof Array)) 2026 { 2027 list = [list]; 2028 } 2029 2030 var points = []; 2031 2032 for (var i = 0; i < list.length; i++) 2033 { 2034 var p = new mxPoint(parseFloat(list[i].x) - dx, parseFloat(list[i].y) - dy) 2035 points.push(p); 2036 absPoints.push(p); 2037 } 2038 2039 edge.geometry.points = points; 2040 } 2041 2042 absPoints.push(endP); 2043 } 2044 return absPoints; 2045}; 2046 2047//TODO improve similarity handling 2048mxGraphMlCodec.prototype.addEdgeStyle = function (edge, styleObj, styleMap) 2049{ 2050 var dashStyleFn = function(val, map) 2051 { 2052 map["dashed"] = 1; 2053 //map["fixDash"] = 1; 2054 var pattern = null; 2055 switch(val) 2056 { 2057 case "DashDot": 2058 pattern = "3 1 1 1"; 2059 break; 2060 case "Dot": 2061 pattern = "1 1"; 2062 break; 2063 case "DashDotDot": 2064 pattern = "3 1 1 1 1 1"; 2065 break; 2066 case "Dash": 2067 pattern = "3 1"; 2068 break; 2069 default: 2070 pattern = val.replace(/0/g, '1'); 2071 } 2072 2073 if (pattern) 2074 { 2075 //Some patterns in graphML has only one number 2076 if (pattern.indexOf(" ") < 0) 2077 { 2078 pattern = pattern + " " + pattern; 2079 } 2080 map["dashPattern"] = pattern; 2081 } 2082 }; 2083 2084 var desktopLineStyleFn = function(val, map) 2085 { 2086 if (val != "line") 2087 map["dashed"] = 1; 2088 2089 var pattern = null; 2090 2091 switch(val) 2092 { 2093 case "dashed": 2094 pattern = "3 1"; 2095 break; 2096 case "dotted": 2097 pattern = "1 1"; 2098 break; 2099 case "dashed_dotted": 2100 pattern = "3 2 1 2"; 2101 break; 2102 } 2103 2104 if (pattern) 2105 map["dashPattern"] = pattern; 2106 }; 2107 2108 // can be mapping to WHITE => empty, BLACK => filled 2109 var endArrowFill = function(val, map) 2110 { 2111 map["endFill"] = (val == 'WHITE' || val.indexOf("white_") == 0 || val.indexOf("transparent_") == 0)? "0" : "1"; 2112 }; 2113 // can be mapping to WHITE => empty, BLACK => filled 2114 var startArrowFill = function(val, map) 2115 { 2116 map["startFill"] = (val == 'WHITE' || val.indexOf("white_") == 0 || val.indexOf("transparent_") == 0)? "0" : "1"; 2117 }; 2118 2119 var startArrow = function(val, map) 2120 { 2121 map["startArrow"] = mxGraphMlArrowsMap[val] || "classic"; 2122 startArrowFill(val, map); 2123 }; 2124 2125 var endArrow = function(val, map) 2126 { 2127 map["endArrow"] = mxGraphMlArrowsMap[val] || "classic"; 2128 endArrowFill(val, map); 2129 } 2130 2131 var desktopEdge = { 2132 "defaults" : 2133 { 2134 "rounded": 0, 2135 "endArrow": "none" 2136 }, 2137 "configuration": {key: "shape", mod: "shape"}, 2138 "y:LineStyle": { 2139 "color": {key: "strokeColor", mod: "color"}, 2140 "type": desktopLineStyleFn, 2141 "width": "strokeWidth" 2142 }, 2143 "y:Arrows": { 2144 "source": startArrow, 2145 "target": endArrow 2146 }, 2147 "y:BendStyle": { 2148 "smoothed": {key: "rounded", mod: "bool"} 2149 } 2150 }; 2151 2152 var arcEdgeStyle = mxUtils.clone(desktopEdge); 2153 arcEdgeStyle["defaults"]["curved"] = "1"; 2154 2155 this.mapObject(styleObj, { 2156 "yjs:PolylineEdgeStyle": { 2157 "defaults" : 2158 { 2159 "endArrow": "none", 2160 "rounded": 0 2161 }, 2162 "smoothingLength": function(val, map) 2163 { 2164 map["rounded"] = (val && parseFloat(val) > 0)? "1" : "0"; 2165 }, 2166 "stroke": {key: "strokeColor", mod: "color"}, 2167 "stroke.yjs:Stroke": 2168 { 2169 "dashStyle": dashStyleFn, 2170 "dashStyle.yjs:DashStyle.dashes": dashStyleFn, 2171 "fill": {key: "strokeColor", mod: "color"}, 2172 "fill.yjs:SolidColorFill.color": {key: "strokeColor", mod: "color"}, 2173 //"lineCap": "", //?? 2174 "thickness.sys:Double": "strokeWidth", 2175 "thickness": "strokeWidth" 2176 }, 2177 "targetArrow": {key: "endArrow", mod: "arrow"}, 2178 "targetArrow.yjs:Arrow": { 2179 "defaults" : 2180 { 2181 "endArrow": "classic", 2182 "endFill": "1", 2183 "endSize": "6" 2184 }, 2185// cropLength: "", //?? 2186 "fill": endArrowFill, 2187 "scale": {key: "endSize", mod: "scale", scale: 5}, 2188// stroke: "", //? 2189 "type": {key: "endArrow", mod: "arrow"} 2190 }, 2191 "sourceArrow": {key: "startArrow", mod: "arrow"}, 2192 "sourceArrow.yjs:Arrow": { 2193 "defaults" : 2194 { 2195 "startArrow": "classic", 2196 "startFill": "1", 2197 "startSize": "6" 2198 }, 2199// cropLength: "", //?? 2200 "fill": startArrowFill, 2201 "scale": {key: "startSize", mod: "scale", scale: 5}, 2202// stroke: "", //? 2203 "type": {key: "startArrow", mod: "arrow"} 2204 } 2205 }, 2206 "y:PolyLineEdge": desktopEdge, 2207 "y:GenericEdge": desktopEdge, 2208 //We approximate all curved types with curve 2209 "y:ArcEdge": arcEdgeStyle, 2210 "y:BezierEdge": arcEdgeStyle, 2211 "y:QuadCurveEdge": arcEdgeStyle, 2212 "y:SplineEdge": arcEdgeStyle 2213 }, styleMap); 2214}; 2215 2216//TODO label offset 2217//TODO labels object is over swim lanes collapse button 2218mxGraphMlCodec.prototype.addLabels = function (node, lblObj, nodeStyle, graph, absPoints) 2219{ 2220 var lastChildIndex = node.getChildCount(); 2221 var lblList = lblObj[mxGraphMlConstants.Y_LABEL] || lblObj; 2222 2223 var lblTxts = []; 2224 var lblStyles = []; 2225 var lblLayouts = []; 2226 2227 if (lblList) 2228 { 2229 if (!(lblList instanceof Array)) 2230 { 2231 lblList = [lblList]; 2232 } 2233 2234 for (var i = 0; i < lblList.length; i++) 2235 { 2236 var lbl = lblList[i]; 2237// console.log(lbl); 2238 var styleMap = {}; 2239 var txt = lbl[mxGraphMlConstants.TEXT] || lbl; 2240 2241 if (txt) txt = txt["#text"]; 2242 2243 //layout 2244 var layout = lbl[mxGraphMlConstants.LAYOUTPARAMETER] || lbl || {}; 2245 2246 //style 2247 var fontStyleFn = function(val, map) 2248 { 2249 if (val) 2250 { 2251 val = val.toUpperCase(); 2252 } 2253 2254 var style = map["fontStyle"] || 0; 2255 2256 switch(val) 2257 { 2258 case "ITALIC": 2259 style = style | 2; 2260 break; 2261 case "BOLD": 2262 style = style | 1; 2263 break; 2264 case "UNDERLINE": 2265 style = style | 4; 2266 break; 2267 } 2268 map["fontStyle"] = style; 2269 }; 2270 2271 var underlineStyleFn = function(val, map) 2272 { 2273 var style = map["fontStyle"] || 0; 2274 2275 if (val == "true") 2276 { 2277 style = style | 4; 2278 } 2279 map["fontStyle"] = style; 2280 }; 2281 2282 this.mapObject(lbl, { 2283 "Style.yjs:DefaultLabelStyle": 2284 { 2285 "backgroundFill" : {key: "labelBackgroundColor", mod: "color"}, 2286 "backgroundFill.yjs:SolidColorFill.color" : {key: "labelBackgroundColor", mod: "color"}, 2287 "backgroundStroke" : {key: "labelBorderColor", mod: "color"}, 2288 "backgroundStroke.yjs:Stroke.fill" : {key: "labelBorderColor", mod: "color"}, 2289 "textFill": {key: "fontColor", mod: "color"}, 2290 "textFill.yjs:SolidColorFill.color": {key: "fontColor", mod: "color"}, 2291 "textSize": "fontSize", 2292 "horizontalTextAlignment": "align", 2293 "verticalTextAlignment": "verticalAlign", 2294 "wrapping": function(val, map) 2295 { 2296 //TODO mxGraph has a single type of wrapping only 2297 if (val) 2298 map["whiteSpace"] = "wrap"; 2299 }, 2300 "font.yjs:Font": 2301 { 2302 "fontFamily": "fontFamily", 2303 "fontSize": "fontSize", 2304 "fontStyle": fontStyleFn, 2305 "fontWeight": fontStyleFn, 2306 "textDecoration": fontStyleFn 2307 } 2308 }, 2309 "Style.y:VoidLabelStyle": function (val, map) 2310 { 2311 map["VoidLbl"] = true; 2312 }, 2313 //Desktop format 2314 //hasBackgroundColor="false" hasLineColor="false" hasText="false" height="4.0" iconTextGap="4" modelName="custom" visible="true" width="4.0" x="26.277050018310547" y="70.76200103759766"> 2315 "alignment": "align", 2316 //"autoSizePolicy": "",//?? 2317 "fontFamily": "fontFamily", 2318 "fontSize": "fontSize", 2319 "fontStyle": fontStyleFn, 2320 "underlinedText": underlineStyleFn, 2321 "horizontalTextPosition": "",//?? how this is compared to alignment? 2322 "textColor": {key: "fontColor", mod: "color"}, 2323 "verticalTextPosition": "verticalAlign", 2324 "hasText": {key: "hasText", mod: "bool"}, 2325 "rotationAngle": "rotation" 2326 }, styleMap); 2327 2328 if (!styleMap["VoidLbl"] && styleMap["hasText"] != "0") 2329 { 2330 lblTxts.push(txt); 2331 lblStyles.push(styleMap); 2332 lblLayouts.push(layout); 2333 } 2334 } 2335 } 2336 2337 //TODO Use the style map with defaults to change the style 2338 for (var i = 0; i < lblTxts.length; i++) 2339 { 2340 if (lblTxts[i]) 2341 { 2342 if (lblLayouts[i] && lblLayouts[i]["bpmn:ParticipantParameter"]) 2343 continue; 2344 2345 lblTxts[i] = mxUtils.htmlEntities(lblTxts[i], false).replace(/\n/g, '<br/>'); 2346 var geo = node.geometry; 2347 2348 var lblCell = new mxCell(lblTxts[i], new mxGeometry(0, 0, geo.width, geo.height), 'text;html=1;spacing=0;' + this.styleMap2Str(lblStyles[i])); 2349 lblCell.vertex = true; 2350 node.insert(lblCell, lastChildIndex); 2351 var lGeo = lblCell.geometry; 2352 2353// console.log(lblTxts[i]); 2354// console.log(lblLayouts[i]); 2355 2356 if (lblLayouts[i]["y:RatioAnchoredLabelModelParameter"]) 2357 { 2358 var strSize = mxUtils.getSizeForString(lblTxts[i], lblStyles[i]["fontSize"], lblStyles[i]["fontFamily"]); 2359 var offsetStr = lblLayouts[i]["y:RatioAnchoredLabelModelParameter"]["LayoutOffset"]; 2360 2361 if (offsetStr) 2362 { 2363 var parts = offsetStr.split(','); 2364 lGeo.x = parseFloat(parts[0]); 2365 lGeo.y = parseFloat(parts[1]); 2366 lGeo.width = strSize.width; 2367 lGeo.height = strSize.height; 2368 lblCell.style += ";spacingTop=-4;"; 2369 } 2370 else 2371 { 2372 //TODO map there? 2373 var lblRatio = lblLayouts[i]["y:RatioAnchoredLabelModelParameter"]["LabelRatio"]; 2374 var layoutRatio = lblLayouts[i]["y:RatioAnchoredLabelModelParameter"]["LayoutRatio"]; 2375 2376 lblCell.style += ";align=center;"; 2377 } 2378 } 2379 else if (lblLayouts[i]["y:InteriorLabelModel"]) //TODO this is probably can be done by setting the value? 2380 { 2381 //TODO merge with next one if they are identical in all cases! 2382 switch (lblLayouts[i]["y:InteriorLabelModel"]) 2383 { 2384 case "Center": 2385 lblCell.style += ";verticalAlign=middle;"; 2386 break; 2387 case "North": 2388 lGeo.height = 1; 2389 break; 2390 case "West": 2391 lGeo.width = geo.height; 2392 lGeo.height = geo.width; 2393 //-90 rotation of origin 2394 lGeo.y = geo.height /2 - geo.width /2; 2395 lGeo.x = -lGeo.y; 2396 lblCell.style += ";rotation=-90"; 2397 break; 2398 } 2399 lblCell.style += ";align=center;"; 2400 } 2401 //TODO Spacing still need to be adjusted 2402 else if (lblLayouts[i]["y:StretchStripeLabelModel"] || lblLayouts[i]["y:StripeLabelModelParameter"]) 2403 { 2404 //TODO merge with previous one if they are identical in all cases! 2405 var dir = lblLayouts[i]["y:StretchStripeLabelModel"] || lblLayouts[i]["y:StripeLabelModelParameter"]["Position"]; 2406 switch (dir) 2407 { 2408 case "North": 2409 lGeo.height = 1; 2410 break; 2411 case "West": 2412 lGeo.width = geo.height; 2413 lGeo.height = geo.width; 2414 //-90 rotation of origin 2415 lGeo.y = geo.height /2 - geo.width /2; 2416 lGeo.x = -lGeo.y; 2417 lblCell.style += ";rotation=-90;"; 2418 break; 2419 } 2420 } 2421 else if (lblLayouts[i]["bpmn:PoolHeaderLabelModel"]) 2422 { 2423 //TODO merge with previous one if they are identical in all cases! 2424 switch (lblLayouts[i]["bpmn:PoolHeaderLabelModel"]) 2425 { 2426 case "NORTH": 2427 lGeo.height = 1; 2428 break; 2429 case "WEST": 2430 lGeo.width = geo.height; 2431 lGeo.height = geo.width; 2432 //-90 rotation of origin 2433 lGeo.y = geo.height /2 - geo.width /2; 2434 lGeo.x = -lGeo.y; 2435 lblCell.style += ";rotation=-90;"; 2436 break; 2437 } 2438 lblCell.style += ";align=center;"; 2439 } 2440 else if (lblLayouts[i]["y:InteriorStretchLabelModelParameter"]) 2441 { 2442 //TODO probably mapObject is needed in this method in general 2443 try { 2444 var insets = lblLayouts[i]["y:InteriorStretchLabelModelParameter"]["Model"]["y:InteriorStretchLabelModel"]["Insets"]; 2445 //TODO how to map it? 2446 } catch(e) { 2447 //Ignore 2448 } 2449 lblCell.style += ";align=center;"; 2450 } 2451 else if (lblLayouts[i]["y:ExteriorLabelModel"]) 2452 { 2453 var lblPos; 2454 switch (lblLayouts[i]["y:ExteriorLabelModel"]) 2455 { 2456 case "East": 2457 lblCell.style += ";labelPosition=right;verticalLabelPosition=middle;align=left;verticalAlign=middle;"; 2458 break; 2459 case "South": 2460 lblCell.style += ";labelPosition=center;verticalLabelPosition=bottom;align=center;verticalAlign=top;"; 2461 break; 2462 case "North": 2463 lblCell.style += ";labelPosition=center;verticalLabelPosition=top;align=center;verticalAlign=bottom;" 2464 break; 2465 case "West": 2466 lblCell.style += ";labelPosition=left;verticalLabelPosition=middle;align=right;verticalAlign=middle;"; 2467 break; 2468 } 2469 } 2470 else if (lblLayouts[i]["y:FreeEdgeLabelModelParameter"]) 2471 { 2472 lGeo.relative = true; 2473 lGeo.adjustIt = true; 2474 var layout = lblLayouts[i]["y:FreeEdgeLabelModelParameter"]; 2475 var ratio = layout["Ratio"]; 2476 var distance = layout["Distance"]; 2477 var angle = layout["Angle"]; 2478 2479 //The geometry is adjusted after finishing the graph import (in decode method) 2480 if (ratio) 2481 { 2482 lGeo.x = parseFloat(ratio); 2483 } 2484 2485 if (distance) 2486 { 2487 lGeo.y = parseFloat(distance); 2488 } 2489 2490 if (angle) 2491 { 2492 lblCell.style += ";rotation=" + (parseFloat(angle) * (180 / Math.PI)); 2493 } 2494 2495 lblCell.style += ";verticalAlign=middle;"; 2496 } 2497 else if (lblLayouts[i]["y:EdgePathLabelModelParameter"]) 2498 { 2499 lGeo.relative = true; 2500 var layout = lblLayouts[i]["y:EdgePathLabelModelParameter"]; 2501 var side = layout["SideOfEdge"]; 2502 var ratio = layout["SegmentRatio"]; 2503 2504 lGeo.x = ratio? (2 * parseFloat(ratio) - 1) : 0; 2505 2506 //TODO this is an approximation, it needs to take into consideration the segment direction and label size 2507 if (side) 2508 { 2509 switch(side) 2510 { 2511 case "RightOfEdge": 2512 lGeo.y = -15; 2513 break; 2514 case "LeftOfEdge": 2515 lGeo.y = 15; 2516 break; 2517 } 2518 } 2519 2520 lblCell.style += ";verticalAlign=middle;"; 2521 2522 } 2523 else //Desktop format or edge 2524 { 2525 var lblX = parseFloat(lblLayouts[i]["x"]), 2526 lblY = parseFloat(lblLayouts[i]["y"]); 2527 2528 if (lblLayouts[i]["width"]) lGeo.width = parseFloat(lblLayouts[i]["width"]); 2529 if (lblLayouts[i]["height"]) lGeo.height = parseFloat(lblLayouts[i]["height"]); 2530 2531 if (node.edge) 2532 { 2533 lGeo.relative = true; 2534 lGeo.x = 0; 2535 lGeo.y = 0; 2536 var dx = node.source.geometry.getCenterX() - node.target.geometry.getCenterX(); 2537 var dy = node.source.geometry.getCenterY() - node.target.geometry.getCenterY(); 2538 2539 if (graph && absPoints && lblLayouts[i]["y:ModelParameter"] && lblLayouts[i]["y:ModelParameter"]["y:SmartEdgeLabelModelParameter"]) 2540 { 2541 var layout = lblLayouts[i]["y:ModelParameter"]["y:SmartEdgeLabelModelParameter"]; 2542 var angle = parseFloat(layout.angle), distance = parseFloat(layout.distance), distanceToCenter = layout.distanceToCenter == "true", 2543 position = layout.position, ratio = parseFloat(layout.ratio), segment = parseFloat(layout.segment); 2544 2545 var eState = new mxCellState(); 2546 eState.absolutePoints = absPoints; 2547 graph.view.updateEdgeBounds(eState); 2548 var sign = (position == "left"? 1 : -1); 2549 2550 if (segment == -1 && angle == 6.283185307179586) 2551 { 2552 //TODO FIXME this case is still incorrect 2553 lGeo.offset = new mxPoint(Math.abs(ratio) < 1? eState.segments[0] * ratio : ratio, sign * distance); 2554 } 2555 else 2556 { 2557 if (segment == -1) segment = 0; 2558 //get the edge cell state to get the segments 2559 var dist = 0; 2560 for (var k = 0; k < segment; k++) 2561 { 2562 dist += eState.segments[k]; 2563 } 2564 2565 dist += eState.segments[segment] * ratio; 2566 lGeo.x = 2 * (dist / eState.length) - 1; 2567 lGeo.y = ((position == "center"? 0 : distance) + lGeo.height/2 * sign * (Math.abs(dx) > Math.abs(dy)? 1 : -1)) * sign; 2568 } 2569 } 2570 else if (!isNaN(lblX) && !isNaN(lblY)) 2571 { 2572 lGeo.offset = new mxPoint(lblX + dx/2 + (dx > 0? -lGeo.width : lGeo.width), lblY); 2573 } 2574 } 2575 else 2576 { 2577 lGeo.x = lblX || 0; 2578 lGeo.y = lblY || 0; 2579 } 2580 } 2581 2582 if (lblStyles[i]["rotation"]) 2583 { 2584 //TODO fix label coordinates after rotation 2585 //console.log(lGeo, lblStyles[i]["rotation"]); 2586 if (lblStyles[i]["rotation"] == 270) 2587 { 2588 lGeo.x -= lGeo.height/2; 2589 } 2590 } 2591 } 2592 } 2593 return {lblTxts: lblTxts, lblStyles: lblStyles}; 2594}; 2595 2596 2597mxGraphMlCodec.prototype.processPage = function (graph, pageIndex) 2598{ 2599 var codec = new mxCodec(); 2600 var node = codec.encode(graph.getModel()); 2601 node.setAttribute("style", "default-style2"); 2602 var modelString = mxUtils.getXml(node); 2603 2604 var output = "<diagram name=\"Page " + pageIndex + "\">"; 2605 output += Graph.compress(modelString); 2606 output += "</diagram>"; 2607 return output; 2608 2609}; 2610 2611//These are the same as mxVsdxUtils functions, but added here to be self-dependent 2612/** 2613 * Returns a collection of direct child Elements that match the specified tag name 2614 * @param {*} parent the parent whose direct children will be processed 2615 * @param {string} name the child tag name to match 2616 * @return {*[]} a collection of matching Elements 2617 */ 2618mxGraphMlCodec.prototype.getDirectChildNamedElements = function (parent, name) { 2619 var result = ([]); 2620 for (var child = parent.firstChild; child != null; child = child.nextSibling) { 2621 if ((child != null && (child.nodeType == 1)) && (name == child.nodeName)) { 2622 /* add */ result.push(child); 2623 } 2624 } 2625 ; 2626 return result; 2627}; 2628 2629mxGraphMlCodec.prototype.getDirectFirstChildNamedElements = function (parent, name) { 2630 for (var child = parent.firstChild; child != null; child = child.nextSibling) { 2631 if ((child != null && (child.nodeType == 1)) && (name == child.nodeName)) { 2632 return child; 2633 } 2634 } 2635 ; 2636 return null; 2637}; 2638 2639/** 2640 * Returns a collection of direct child Elements 2641 * @param {*} parent the parent whose direct children will be processed 2642 * @return {*[]} a collection of all child Elements 2643 */ 2644mxGraphMlCodec.prototype.getDirectChildElements = function (parent) { 2645 var result = ([]); 2646 for (var child = parent.firstChild; child != null; child = child.nextSibling) { 2647 if (child != null && (child.nodeType == 1)) { 2648 /* add */ result.push(child); 2649 } 2650 } 2651 ; 2652 return result; 2653}; 2654/** 2655 * Returns the first direct child Element 2656 * @param {*} parent the parent whose direct first child will be processed 2657 * @return {*} the first child Element 2658 */ 2659mxGraphMlCodec.prototype.getDirectFirstChildElement = function (parent) { 2660 for (var child = parent.firstChild; child != null; child = child.nextSibling) { 2661 if (child != null && (child.nodeType == 1)) { 2662 return child; 2663 } 2664 } 2665 ; 2666 return null; 2667}; 2668 2669var mxGraphMlConverters = //TODO this code is taken from yworks.com. Is that OK? 2670{ 2671 "orgchartconverters.linebreakconverter": function(e, t) { 2672 if (typeof e === "string") { 2673 var i = e; 2674 while (i.length > 20 && i.indexOf(" ") > -1) 2675 i = i.substring(0, i.lastIndexOf(" ")); 2676 return t === "true" ? i : e.substring(i.length) 2677 } 2678 return "" 2679 }, 2680 "orgchartconverters.borderconverter": function(e, t) { 2681 return typeof e === "boolean" ? e ? "#FFBB33" : "rgba(0,0,0,0)" : "#FFF" 2682 }, 2683 "orgchartconverters.addhashconverter": function(e, t) { 2684 return typeof e === "string" ? typeof t === "string" ? "#" + e + t : "#" + e : e 2685 }, 2686 "orgchartconverters.intermediateconverter": function(e, t) { 2687 return typeof e === "string" && e.length > 17 ? e.replace(/^(.)(\S*)(.*)/, "$1.$3") : e 2688 }, 2689 "orgchartconverters.overviewconverter": function(e, t) { 2690 return typeof e === "string" && e.length > 0 ? e.replace(/^(.)(\S*)(.*)/, "$1.$3") : "" 2691 } 2692}; 2693 2694var mxGraphMlArrowsMap = 2695{ 2696 "SIMPLE": "open", 2697 "TRIANGLE": "block", 2698 "DIAMOND": "diamond", 2699 "CIRCLE": "oval", 2700 "CROSS": "cross", 2701 "SHORT": "classicThin", 2702 "DEFAULT": "classic", 2703 "NONE": "none", 2704 //desktop 2705 "none": "none", 2706 "white_delta_bar": "block", //FIXME not a match 2707 "delta": "block", 2708 "standard": "classic", 2709 "diamond": "diamond", 2710 "white_diamond": "diamond", 2711 "white_delta": "block", 2712 "plain": "open", 2713 "skewed_dash": "dash", 2714 "concave": "openThin", //FIXME not exact match 2715 "transparent_circle": "oval", 2716 "crows_foot_many": "ERmany", 2717 "crows_foot_one": "ERone", 2718 "crows_foot_one_optional": "ERzeroToOne", 2719 "crows_foot_one_mandatory": "ERmandOne", 2720 "crows_foot_many_optional": "ERzeroToMany", 2721 "crows_foot_many_mandatory": "ERoneToMany", 2722 "white_circle": "oval", 2723 "t_shape": "ERone", //FIXME not a match 2724 "short": "classicThin", 2725 "convex": "", //FIXME not a match 2726 "cross": "cross" 2727 2728}; 2729 2730var mxGraphMlShapesMap = 2731{ 2732 "star5": "mxgraph.basic.star;flipV=1", //TODO This is not close enough! 2733 "star6": "mxgraph.basic.6_point_star",//;rotation=30", //TODO requires rotation! 2734 "star8": "mxgraph.basic.8_point_star", 2735 "sheared_rectangle": "parallelogram", 2736 "sheared_rectangle2": "parallelogram;flipH=1", 2737 "hexagon": "hexagon", 2738 "octagon": "mxgraph.basic.octagon", 2739 "ellipse": "ellipse", 2740 "round_rectangle": "rect;rounded=1;arcsize=30", 2741 "diamond": "rhombus", 2742 "fat_arrow": "step;perimeter=stepPerimeter", 2743 "fat_arrow2": "step;perimeter=stepPerimeter;flipH=1", 2744 "trapez": "trapezoid;perimeter=trapezoidPerimeter;flipV=1", 2745 "trapez2": "trapezoid;perimeter=trapezoidPerimeter", 2746 "triangle": "triangle",//;rotation=-90", //TODO requires rotation! 2747 "triangle2": "triangle",//;rotation=90", //TODO requires rotation! 2748 "rectangle": "rect", 2749 "rectangle3d": "", //TODO create this shape 2750 "roundrectangle": "rect;rounded=1;arcsize=30", 2751 "fatarrow": "step;perimeter=stepPerimeter", 2752 "fatarrow2": "step;perimeter=stepPerimeter;flipH=1", 2753 "parallelogram": "parallelogram", 2754 "parallelogram2": "parallelogram;flipH=1", 2755 "trapezoid2": "trapezoid;perimeter=trapezoidPerimeter;flipV=1", 2756 "trapezoid": "trapezoid;perimeter=trapezoidPerimeter", 2757 //Bevel TODO make them looks closer to yEd 2758 "bevelnode": "rect;glass=1;", 2759 "bevelnodewithshadow": "rect;glass=1;shadow=1", 2760 "bevelnode2": "rect;glass=1;rounded=1;arcsize=30", 2761 "bevelnode3": "rect;glass=1;rounded=1;arcsize=30;shadow=1", 2762 "shinyplatenode": "rect;glass=1",//;rotation=-90",//TODO requires rotation! 2763 "shinyplatenodewithshadow": "rect;glass=1;shadow=1",//;rotation=-90",//TODO requires rotation! 2764 "shinyplatenode2": "rect;glass=1;rounded=1;arcsize=30",//;rotation=-90",//TODO requires rotation! 2765 "shinyplatenode3": "rect;glass=1;rounded=1;arcsize=30;shadow=1",//;rotation=-90",//TODO requires rotation! 2766 //Table 2767// "yed_table_node 2768 //flowchart 2769 "process": "mxgraph.flowchart.process", 2770 "decision": "mxgraph.flowchart.decision", 2771 "start1": "mxgraph.flowchart.start_1", 2772 "start2": "mxgraph.flowchart.start_2;aspect=fixed", 2773 "terminator": "mxgraph.flowchart.terminator", 2774 "cloud": "cloud", 2775 "data": "mxgraph.flowchart.data", 2776 "directdata": "mxgraph.flowchart.direct_data", 2777 "database": "mxgraph.flowchart.database", 2778 "document": "mxgraph.flowchart.document", 2779 "predefinedprocess": "mxgraph.flowchart.predefined_process", 2780 "storeddata": "mxgraph.flowchart.stored_data", 2781 "internalstorage": "mxgraph.flowchart.internal_storage", 2782 "sequentialdata": "mxgraph.flowchart.sequential_data;aspect=fixed", 2783 "manualinput": "mxgraph.flowchart.manual_input", 2784 "card": "card;size=10", 2785 "papertype": "mxgraph.flowchart.paper_tape", 2786 "delay": "mxgraph.flowchart.delay", 2787 "display": "mxgraph.flowchart.display", 2788 "manualoperation": "mxgraph.flowchart.manual_operation", 2789 "preparation": "mxgraph.flowchart.preparation", 2790 "looplimit": "mxgraph.flowchart.loop_limit", 2791 "looplimitend": "mxgraph.flowchart.loop_limit;flipV=1", 2792 "onpagereference": "mxgraph.flowchart.on-page_reference;aspect=fixed", 2793 "offpagereference": "mxgraph.flowchart.off-page_reference;aspect=fixed", 2794 "annotation": "mxgraph.flowchart.annotation_1", //TODO not similar! 2795 "usermessage": "mxgraph.arrows2.arrow;dy=0;dx=10;notch=0", //TODO requires rotation! 2796 "networkmessage": "mxgraph.arrows2.arrow;dy=0;dx=0;notch=10", 2797 //The same like above but with "com.yworks.flowchart." prefex. TODO should we just remove the prefex? 2798 "com.yworks.flowchart.start1": "mxgraph.flowchart.start_1", 2799 "com.yworks.flowchart.start2": "mxgraph.flowchart.start_2;aspect=fixed", 2800 "com.yworks.flowchart.terminator": "mxgraph.flowchart.terminator", 2801 "com.yworks.flowchart.process": "mxgraph.flowchart.process", 2802 "com.yworks.flowchart.predefinedprocess": "mxgraph.flowchart.predefined_process", 2803 "com.yworks.flowchart.decision": "mxgraph.flowchart.decision", 2804 "com.yworks.flowchart.looplimit": "mxgraph.flowchart.loop_limit", 2805 "com.yworks.flowchart.looplimitend": "mxgraph.flowchart.loop_limit;flipV=1", 2806 "com.yworks.flowchart.document": "mxgraph.flowchart.document", 2807 "com.yworks.flowchart.data": "mxgraph.flowchart.data", 2808 "com.yworks.flowchart.directdata": "mxgraph.flowchart.direct_data", 2809 "com.yworks.flowchart.storeddata": "mxgraph.flowchart.stored_data", 2810 "com.yworks.flowchart.sequentialdata": "mxgraph.flowchart.sequential_data;aspect=fixed", 2811 "com.yworks.flowchart.database": "mxgraph.flowchart.database", 2812 "com.yworks.flowchart.internalstorage": "mxgraph.flowchart.internal_storage", 2813 "com.yworks.flowchart.manualinput": "mxgraph.flowchart.manual_input", 2814 "com.yworks.flowchart.card": "card;size=10", 2815 "com.yworks.flowchart.papertype": "mxgraph.flowchart.paper_tape", 2816 "com.yworks.flowchart.cloud": "cloud", 2817 "com.yworks.flowchart.delay": "mxgraph.flowchart.delay", 2818 "com.yworks.flowchart.display": "mxgraph.flowchart.display", 2819 "com.yworks.flowchart.manualoperation": "mxgraph.flowchart.manual_operation", 2820 "com.yworks.flowchart.preparation": "mxgraph.flowchart.preparation", 2821 "com.yworks.flowchart.onpagereference": "mxgraph.flowchart.on-page_reference;aspect=fixed", 2822 "com.yworks.flowchart.offpagereference": "mxgraph.flowchart.off-page_reference;aspect=fixed", 2823 "com.yworks.flowchart.usermessage": "mxgraph.arrows2.arrow;dy=0;dx=10;notch=0", //TODO requires rotation! 2824 "com.yworks.flowchart.networkmessage": "mxgraph.arrows2.arrow;dy=0;dx=0;notch=10", 2825 "com.yworks.flowchart.annotation": "mxgraph.flowchart.annotation_1", //TODO not similar! 2826 2827 //icons (network) 2828 "database.svg": "mxgraph.networks.storage", //TODO not similar! 2829 "laptop.svg": "mxgraph.networks.laptop",//TODO not similar! 2830 "server.svg": "mxgraph.networks.server",//TODO not similar! 2831 "smartphone.svg": "mxgraph.networks.mobile",//TODO not similar! //TODO fixed aspect ratio 2832 "switch.svg": "mxgraph.networks.switch",//TODO not similar! //TODO fixed aspect ratio 2833 "wlan.svg": "mxgraph.networks.wireless_hub",//TODO not similar! 2834 "workstation.svg": "mxgraph.networks.pc",//TODO not similar! 2835 //bpmn 2836 "transaction": "ext;double=1;rounded=1", 2837 "sub_process": "ext;rounded=1", 2838 "call_activity": "ext;rounded=1;strokeWidth=3", 2839 //TODO two colors for stroke! 2840 "exclusive_with_marker": "mxgraph.bpmn.shape;perimeter=rhombusPerimeter;background=gateway;outline=none;symbol=exclusiveGw", 2841 "event_based": "mxgraph.bpmn.shape;perimeter=rhombusPerimeter;background=gateway;outline=boundInt;symbol=multiple", 2842 "parallel": "mxgraph.bpmn.shape;perimeter=rhombusPerimeter;background=gateway;outline=none;symbol=parallelGw", 2843 "inclusive": "mxgraph.bpmn.shape;perimeter=rhombusPerimeter;background=gateway;outline=end;symbol=general", 2844 "complex": "mxgraph.bpmn.shape;perimeter=rhombusPerimeter;background=gateway;outline=none;symbol=complexGw", 2845 "exclusive_event_based": "mxgraph.bpmn.shape;perimeter=rhombusPerimeter;background=gateway;outline=standard;symbol=multiple", 2846 "parallel_event_based": "mxgraph.bpmn.shape;perimeter=rhombusPerimeter;background=gateway;outline=standard;symbol=parallelMultiple", 2847 //hexagon 2848 "calling_global_conversation": "hexagon;strokeWidth=4", 2849 //mxgraph.bpmn.shape;perimeter=ellipsePerimeter;symbol=general 2850 "message": "mxgraph.bpmn.shape;perimeter=ellipsePerimeter;symbol=message", 2851 "timer": "mxgraph.bpmn.shape;perimeter=ellipsePerimeter;symbol=timer", 2852 "escalation": "mxgraph.bpmn.shape;perimeter=ellipsePerimeter;symbol=escalation", 2853 "conditional": "mxgraph.bpmn.shape;perimeter=ellipsePerimeter;symbol=conditional", 2854 "link": "mxgraph.bpmn.shape;perimeter=ellipsePerimeter;symbol=link", 2855 "error": "mxgraph.bpmn.shape;perimeter=ellipsePerimeter;symbol=error", 2856 "cancel": "mxgraph.bpmn.shape;perimeter=ellipsePerimeter;symbol=cancel", 2857 "compensation": "mxgraph.bpmn.shape;perimeter=ellipsePerimeter;symbol=compensation", 2858 "signal": "mxgraph.bpmn.shape;perimeter=ellipsePerimeter;symbol=signal", 2859 "multiple": "mxgraph.bpmn.shape;perimeter=ellipsePerimeter;symbol=multiple", 2860 "parallel_multiple": "mxgraph.bpmn.shape;perimeter=ellipsePerimeter;symbol=parallelMultiple", 2861 "terminate": "mxgraph.bpmn.shape;perimeter=ellipsePerimeter;symbol=terminate", 2862 2863// "com.yworks.bpmn.pool 2864 "com.yworks.bpmn.activity.withshadow": "js:bpmnActivityShadow", 2865 "com.yworks.bpmn.activity": "js:bpmnActivity", 2866 "com.yworks.bpmn.gateway.withshadow": "mxgraph.bpmn.shape;perimeter=rhombusPerimeter;background=gateway;shadow=1", 2867 "com.yworks.bpmn.gateway": "mxgraph.bpmn.shape;perimeter=rhombusPerimeter;background=gateway", 2868 "com.yworks.bpmn.event.withshadow": "mxgraph.bpmn.shape;perimeter=ellipsePerimeter;shadow=1", 2869 "com.yworks.bpmn.event": "mxgraph.bpmn.shape;perimeter=ellipsePerimeter", 2870 "com.yworks.bpmn.conversation.withshadow": "hexagon;shadow=1", 2871 "com.yworks.bpmn.conversation": "hexagon", 2872 "com.yworks.bpmn.artifact.withshadow": "js:bpmnArtifactShadow", 2873 "com.yworks.bpmn.artifact": "js:bpmnArtifact", 2874 2875 bpmnOutline: { 2876 "sub_process_interrupting": "eventInt", 2877 "sub_process_non_interrupting": "eventNonint", 2878 "catching": "catching", 2879 "boundary_interrupting": "boundInt", 2880 "boundary_non_interrupting": "boundNonint", 2881 "throwing": "throwing", 2882 "end": "end", 2883 "event_characteristic_start": "standard", 2884 "event_characteristic_end": "end", 2885 "event_characteristic_intermediate_catching": "catching", 2886 "event_characteristic_start_event_sub_process_interrupting": "eventInt", 2887 "event_characteristic_intermediate_boundary_interrupting": "boundInt" 2888 }, 2889 bpmnSymbol: { 2890 "event_type_plain": "general", 2891 "event_type_message": "message", 2892 "event_type_timer": "timer", 2893 "event_type_escalation": "escalation", 2894 "event_type_conditional": "conditional", 2895 "event_type_link": "link", 2896 "event_type_error": "error", 2897 "event_type_cancel": "cancel", 2898 "event_type_compensation": "compensation", 2899 "event_type_signal": "signal", 2900 "event_type_multiple": "multiple", 2901 "event_type_parallel_multiple": "parallelMultiple", 2902 "event_type_terminate": "terminate", 2903 "gateway_type_plain": "", 2904 "gateway_type_data_based_exclusive": "exclusiveGw", 2905 "gateway_type_inclusive": "general;outline=end", 2906 "gateway_type_parallel": "parallelGw", 2907 "gateway_type_complex": "complexGw", 2908 "gateway_type_event_based_exclusive": "multiple;outline=catching", 2909 "gateway_type_event_based_exclusive_start_process": "multiple;outline=standard", 2910 "gateway_type_parallel_event_based_exclusive_start_process": "parallelMultiple;outline=standard", 2911 "conversation_type": "", 2912 "artifact_type_data_object": "js:bpmnDataObject", 2913 "artifact_type_annotation": "mxgraph.flowchart.annotation_1", 2914 "artifact_type_group": "rect;fillColor=none;dashed=1;dashPattern=3 1 1 1;collapsible=0;rounded=1", 2915 "artifact_type_data_store": "datastore", 2916 "artifact_type_reply_message": "message;strokeColor=#000000;fillColor=#A1A1A1", 2917 "artifact_type_request_message": "message", 2918 "connection_type_sequence_flow": "", 2919 "connection_type_default_flow": "", 2920 "connection_type_conditional_flow": "", 2921 "connection_type_association": "", 2922 "connection_type_directed_association": "", 2923 "connection_type_bidirected_association": "", 2924 "connection_type_message_flow": "", 2925 "connection_type_conversation_link": "", 2926 "connection_type_forked_conversation_link": "", 2927 "pool_type_lane_and_column": "", 2928 "pool_type_empty": "", 2929 "pool_type_lane": "", 2930 "pool_type_column": "", 2931 "activity_type": "" 2932 }, 2933 //desktop entity relationship 2934 "com.yworks.entityrelationship.big_entity": "js:relationship_big_entity", 2935 "com.yworks.entityrelationship.small_entity" : "ext", 2936 "com.yworks.entityrelationship.relationship": "rhombus", 2937 "com.yworks.entityrelationship.attribute": "js:relationship_attribute", 2938 //SBGN 2939 "com.yworks.sbgn.unspecifiedentity": "ellipse", 2940 "com.yworks.sbgn.simplechemical": "ellipse", 2941 "com.yworks.sbgn.macromolecule": "ext;rounded=1", 2942 "com.yworks.sbgn.nucleicacidfeature": "", //TODO create this shape! 2943 "com.yworks.sbgn.perturbingagent": "", //TODO create this shape! 2944 "com.yworks.sbgn.phenotype": "hexagon;perimeter=hexagonPerimeter2;size=0.2", 2945 "com.yworks.sbgn.emptyset": "lineEllipse;line=vertical;perimeter=ellipsePerimeter",//;rotation=45", //TODO create this shape! 2946 "com.yworks.sbgn.submap": "", //TODO create this shape! 2947 "com.yworks.sbgn.unitofinformation": "", //TODO create this shape! 2948 "com.yworks.sbgn.statevariable": "mxgraph.flowchart.terminator", 2949 "com.yworks.sbgn.tag": "offPageConnector;size=0.25", //;rotation=90", //TODO create this shape without rotation! 2950 "com.yworks.sbgn.process": "rect", 2951 "com.yworks.sbgn.operator": "ellipse", 2952 2953 //special edges 2954 "com.yworks.edge.framed": "link", 2955 2956 //Male/Female icons (FIXME Not similar and unsafe as it refers to remote resources) 2957 "usericon_female1.svg": "image;image=https://cdn1.iconfinder.com/data/icons/user-pictures/100/female1-128.png", 2958 "usericon_female2.svg": "image;image=https://cdn1.iconfinder.com/data/icons/user-pictures/100/female1-128.png", 2959 "usericon_female3.svg": "image;image=https://cdn1.iconfinder.com/data/icons/user-pictures/100/female1-128.png", 2960 "usericon_female4.svg": "image;image=https://cdn1.iconfinder.com/data/icons/user-pictures/100/female1-128.png", 2961 "usericon_female5.svg": "image;image=https://cdn1.iconfinder.com/data/icons/user-pictures/100/female1-128.png", 2962 "usericon_male1.svg": "image;image=https://cdn1.iconfinder.com/data/icons/user-pictures/101/malecostume-128.png", 2963 "usericon_male2.svg": "image;image=https://cdn1.iconfinder.com/data/icons/user-pictures/101/malecostume-128.png", 2964 "usericon_male3.svg": "image;image=https://cdn1.iconfinder.com/data/icons/user-pictures/101/malecostume-128.png", 2965 "usericon_male4.svg": "image;image=https://cdn1.iconfinder.com/data/icons/user-pictures/101/malecostume-128.png", 2966 "usericon_male5.svg": "image;image=https://cdn1.iconfinder.com/data/icons/user-pictures/101/malecostume-128.png" 2967}; 2968 2969var mxGraphMlConstants = 2970{ 2971 ID: "id", 2972 2973 KEY_FOR: "for", 2974 2975 KEY_NAME: "attr.name", 2976 2977 KEY_TYPE: "attr.type", 2978 2979 KEY_YTYPE: "yfiles.type", 2980 2981 GRAPH: "graph", 2982 2983 GRAPHML: "graphml", 2984 2985 NODE: "node", 2986 2987 EDGE: "edge", 2988 2989 HYPEREDGE: "hyperedge", 2990 2991 PORT: "port", 2992 2993 ENDPOINT: "endpoint", 2994 2995 KEY: "key", 2996 2997 DATA: "data", 2998 2999 ALL: "all", 3000 3001 EDGE_SOURCE: "source", 3002 3003 EDGE_SOURCE_PORT: "sourceport", 3004 3005 EDGE_TARGET: "target", 3006 3007 EDGE_TARGET_PORT: "targetport", 3008 3009 EDGE_DIRECTED: "directed", 3010 3011 EDGE_UNDIRECTED: "undirected", 3012 3013 EDGE_DEFAULT: "edgedefault", 3014 3015 PORT_NAME: "name", 3016 3017 HEIGHT: "Height", 3018 3019 WIDTH: "Width", 3020 3021 X: "X", 3022 3023 Y: "Y", 3024 3025 HEIGHT_L: "height", 3026 3027 WIDTH_L: "width", 3028 3029 X_L: "x", 3030 3031 Y_L: "y", 3032 3033 JGRAPH: "jGraph:", 3034 3035 GEOMETRY: "y:Geometry", 3036 3037 FILL: "Fill", 3038 3039 SHAPENODE: "y:ShapeNode", 3040 3041 SHAPEEDGE: "ShapeEdge", 3042 3043 JGRAPH_URL: "http://www.jgraph.com/", 3044 3045 KEY_NODE_ID: "d0", 3046 3047 KEY_NODE_NAME: "nodeData", 3048 3049 KEY_EDGE_ID: "d1", 3050 3051 KEY_EDGE_NAME: "edgeData", 3052 3053 STYLE: "Style", 3054 3055 SHAPE: "Shape", 3056 3057 TYPE: "type", 3058 3059 LABEL: "label", 3060 3061 TEXT: "text", 3062 3063 PROPERTIES: "properties", 3064 3065 SOURCETARGET: "SourceTarget", 3066 3067 RECT: "y:RectD", 3068 3069 NODE_LABELS: "NodeLabels", 3070 3071 NODE_LABEL: "y:NodeLabel", 3072 3073 NODE_GEOMETRY: "NodeGeometry", 3074 3075 USER_TAGS: "UserTags", 3076 3077 NODE_STYLE: "NodeStyle", 3078 3079 NODE_GRAPHICS: "nodegraphics", 3080 3081 NODE_VIEW_STATE: "NodeViewState", 3082 3083 EDGE_LABELS: "EdgeLabels", 3084 3085 EDGE_GEOMETRY: "EdgeGeometry", 3086 3087 EDGE_STYLE: "EdgeStyle", 3088 3089 EDGE_VIEW_STATE: "EdgeViewState", 3090 3091 PORT_LOCATION_PARAMETER: "PortLocationParameter", 3092 3093 PORT_STYLE: "PortStyle", 3094 3095 PORT_VIEW_STATE: "PortViewState", 3096 3097 SHARED_DATA: "SharedData", 3098 3099 Y_SHARED_DATA: "y:SharedData", 3100 3101 X_KEY: "x:Key", 3102 3103 GRAPHML_REFERENCE: "y:GraphMLReference", 3104 3105 RESOURCE_KEY: "ResourceKey", 3106 3107 Y_RESOURCES: "y:Resources", 3108 3109 Y_RESOURCE: "y:Resource", 3110 3111 REFID: "refid", 3112 3113 X_LIST: "x:List", 3114 3115 X_STATIC: "x:Static", 3116 3117 Y_BEND: "y:Bend", 3118 3119 LOCATION: "Location", 3120 3121 Y_LABEL: "y:Label", 3122 3123 LAYOUTPARAMETER: "LayoutParameter", 3124 3125 YJS_DEFAULTLABELSTYLE: "yjs:DefaultLabelStyle", 3126 3127 MEMBER: "Member" 3128}; 3129 3130 3131EditorUi.prototype.doImportGraphML = function(xmlData, done, onerror) 3132{ 3133 new mxGraphMlCodec().decode(xmlData, done, onerror); 3134}; 3135 3136