import.js 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. /**
  2. * Plugin for Freemind import.
  3. * See https://github.com/jiangxin/freemind-mmx/tree/master/freemind
  4. */
  5. Draw.loadPlugin(function(ui) {
  6. var graph = ui.editor.graph;
  7. // Adds resource for action
  8. mxResources.parse('importFreemind=Freemind');
  9. // Parses Freemind data
  10. function importFreemindData(data)
  11. {
  12. // Gets the default parent for inserting new cells. This
  13. // is normally the first child of the root (ie. layer 0).
  14. var defaultParent = graph.getDefaultParent();
  15. var cells = [];
  16. var defaultWidth = 80;
  17. var defaultHeight = 30;
  18. var mainConceptHeight = 40;
  19. var defaultHorizontalSpaceBetweenVertex = 40;
  20. var defaultVerticalSpaceBetweenVertex = 10;
  21. var freeMindMainConceptVertexStyle = "ellipse;whiteSpace=wrap;html=1;align=center;collapsible=0;container=1;recursiveResize=0;";
  22. var freeMindBranchVertexStyle = "whiteSpace=wrap;html=1;shape=partialRectangle;top=0;left=0;bottom=1;right=0;points=[[0,1],[1,1]];strokeColor=#000000;fillColor=none;align=center;verticalAlign=bottom;routingCenterY=0.5;snapToPoint=1;collapsible=0;container=1;recursiveResize=0;autosize=1;";
  23. var freeMindConceptVertexStyle = "whiteSpace=wrap;html=1;rounded=1;arcSize=50;align=center;verticalAlign=middle;collapsible=0;container=1;recursiveResize=0;strokeWidth=1;autosize=1;spacing=4;";
  24. var freeMindEdgeStyle = "edgeStyle=entityRelationEdgeStyle;startArrow=none;endArrow=none;segment=10;curved=1;html=1;";
  25. // Tells whether or not a node has child ideas
  26. var hasChilds = function(node){
  27. for (var i = 0; i < node.childNodes.length; i++){
  28. if (node.childNodes[i].nodeName == "node"){
  29. return true;
  30. }
  31. }
  32. return false;
  33. };
  34. // Generates useful info on the nodes to be used later.
  35. var generatePreprocessingNodeInfo = function(node){
  36. var childCount = 0;
  37. var maxChildsInHierarchy = 0;
  38. for (var i = 0; i < node.childNodes.length; i++){
  39. var childNode = node.childNodes[i];
  40. if (childNode.nodeName == "node"){
  41. var maxChilds = generatePreprocessingNodeInfo(childNode);
  42. maxChildsInHierarchy = Math.max(maxChildsInHierarchy, maxChilds);
  43. childCount++;
  44. }
  45. }
  46. node.childCount = childCount;
  47. node.maxChilds = Math.max(childCount, maxChildsInHierarchy);
  48. return childCount;
  49. }
  50. // Main node generation funcion (recursive)
  51. var processFreeMindNode = function(node, nodeParent, x, y){
  52. var mainConcept = false;
  53. var vertexStyle = freeMindBranchVertexStyle;
  54. if (nodeParent == defaultParent){
  55. mainConcept = true;
  56. vertexStyle = freeMindMainConceptVertexStyle;
  57. }else if (hasChilds(node)){
  58. // Concept, style appropiately
  59. vertexStyle = freeMindConceptVertexStyle;
  60. }
  61. var nodeName = node.getAttribute('TEXT') || "";
  62. var nodeVertex = graph.insertVertex(defaultParent, null, nodeName, x, y, defaultWidth, defaultHeight, vertexStyle);
  63. graph.cellLabelChanged(nodeVertex,nodeName,true);
  64. if (mainConcept){
  65. nodeVertex.geometry.height = mainConceptHeight; // TODO: Maybe set height according to it's width, so it's rounded?
  66. }
  67. if (nodeParent != defaultParent){
  68. // Don't generate an edge for the first node
  69. graph.insertEdge(defaultParent, null, '', nodeParent, nodeVertex, freeMindEdgeStyle);
  70. }
  71. cells.push(nodeVertex);
  72. // Insert child nodes, on correct positions
  73. var childNumber = 0;
  74. for (var i = 0; i < node.childNodes.length; i++){
  75. var childNode = node.childNodes[i];
  76. if (childNode.nodeName == "node"){
  77. var childX = x + nodeVertex.geometry.width + defaultHorizontalSpaceBetweenVertex;
  78. var childY = y + (defaultHeight + defaultVerticalSpaceBetweenVertex) * childNumber;
  79. childNumber += childNode.maxChilds == 0? 1 : childNode.maxChilds;
  80. processFreeMindNode(childNode, nodeVertex, childX, childY);
  81. }
  82. }
  83. }
  84. // Makes the import one undoable edit
  85. graph.getModel().beginUpdate();
  86. try
  87. {
  88. // Gets point for free space in the graph for insert
  89. var pt = graph.getFreeInsertPoint();
  90. var freeMindParser = new DOMParser();
  91. freeMindDOM = freeMindParser.parseFromString(data, "text/xml");
  92. var freeMindDOMchilds = freeMindDOM.children[0];
  93. // Transverse the childs, and generate relevant input
  94. for (var i = 0; i < freeMindDOMchilds.childNodes.length; i++){
  95. if (freeMindDOMchilds.childNodes[i].nodeName == "node"){
  96. generatePreprocessingNodeInfo(freeMindDOMchilds.childNodes[i]);
  97. }
  98. }
  99. // Generate the nodes
  100. for (var i = 0; i < freeMindDOMchilds.childNodes.length; i++){
  101. if (freeMindDOMchilds.childNodes[i].nodeName == "node"){
  102. processFreeMindNode(freeMindDOMchilds.childNodes[i], defaultParent, pt.x, pt.y);
  103. }
  104. }
  105. // Applies current styles to new cells (might not be needed)
  106. graph.fireEvent(new mxEventObject('cellsInserted', 'cells', cells));
  107. }
  108. finally
  109. {
  110. graph.getModel().endUpdate();
  111. }
  112. // Selects new cells and scrolls into view
  113. graph.setSelectionCells(cells);
  114. graph.scrollCellToVisible(graph.getSelectionCell());
  115. };
  116. // Adds action
  117. ui.actions.addAction('importFreemind...', function()
  118. {
  119. // Only modern browsers for now. We'll move the import
  120. // code above to the main codebase later
  121. if (Graph.fileSupport && !mxClient.IS_IE && !mxClient.IS_IE11)
  122. {
  123. var input = document.createElement('input');
  124. input.setAttribute('type', 'file');
  125. mxEvent.addListener(input, 'change', function()
  126. {
  127. if (input.files != null)
  128. {
  129. // Only one file for now...
  130. var reader = new FileReader();
  131. reader.onload = function(e)
  132. {
  133. importFreemindData(e.target.result);
  134. };
  135. reader.readAsText(input.files[0]);
  136. }
  137. });
  138. input.click();
  139. }
  140. });
  141. // Adds menu
  142. ui.menubar.addMenu('Import', function(menu, parent)
  143. {
  144. ui.menus.addMenuItem(menu, 'importFreemind');
  145. });
  146. // Moves import menu to before help menu
  147. ui.menubar.container.insertBefore(ui.menubar.container.lastChild,
  148. ui.menubar.container.lastChild.previousSibling.previousSibling.previousSibling);
  149. });