import.js
6.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
/**
 * Plugin for Freemind import.
 * See https://github.com/jiangxin/freemind-mmx/tree/master/freemind
 */
Draw.loadPlugin(function(ui)
{
	var graph = ui.editor.graph;
	// Adds resource for action
	mxResources.parse('importFreemind=Freemind');
	// Parses Freemind data
	function importFreemindData(data)
	{
		// Gets the default parent for inserting new cells. This
		// is normally the first child of the root (ie. layer 0).
		var defaultParent = graph.getDefaultParent();
		var cells = [];
		var defaultWidth = 80;
		var defaultHeight = 30;
		var mainConceptHeight = 40;
		var defaultHorizontalSpaceBetweenVertex = 40;
		var defaultVerticalSpaceBetweenVertex = 10;
		var freeMindMainConceptVertexStyle = 'ellipse;whiteSpace=wrap;html=1;align=center;collapsible=0;container=1;recursiveResize=0;';
		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;';
		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;';
		var freeMindEdgeStyle = 'edgeStyle=entityRelationEdgeStyle;startArrow=none;endArrow=none;segment=10;curved=1;html=1;';
		// Tells whether or not a node has child ideas
		var hasChilds = function(node)
		{
			for (var i = 0; i < node.childNodes.length; i++)
			{
				if (node.childNodes[i].nodeName == 'node')
				{
					return true;
				}
			}
			
			return false;
		};
		// Generates useful info on the nodes to be used later.
		var generatePreprocessingNodeInfo = function(node)
		{
			var childCount = 0;
			var maxChildsInHierarchy = 0;
			
			for (var i = 0; i < node.childNodes.length; i++)
			{
				var childNode = node.childNodes[i];
				
				if (childNode.nodeName == 'node')
				{
					var maxChilds = generatePreprocessingNodeInfo(childNode);
					maxChildsInHierarchy = Math.max(maxChildsInHierarchy, maxChilds);
					childCount++;
				}
			}
			
			node.childCount = childCount;
			node.maxChilds = Math.max(childCount, maxChildsInHierarchy);
			return childCount;
		}
		// Main node generation funcion (recursive)
		var processFreeMindNode = function(node, nodeParent, x, y)
		{
			var mainConcept = false;
			var vertexStyle = freeMindBranchVertexStyle;
			
			if (nodeParent == defaultParent)
			{
				mainConcept = true;
				vertexStyle = freeMindMainConceptVertexStyle;
			}
			else if (hasChilds(node))
			{
				// Concept, style appropiately
				vertexStyle = freeMindConceptVertexStyle;
			}
			
			var nodeName = node.getAttribute('TEXT') || '';
			var nodeVertex = graph.insertVertex(defaultParent, null, nodeName, x, y, defaultWidth,
					defaultHeight, vertexStyle);
			graph.cellLabelChanged(nodeVertex, nodeName, true);
			
			if (mainConcept)
			{
				nodeVertex.geometry.height = mainConceptHeight; // TODO: Maybe set height according to it's width, so it's rounded?
			}
			
			if (nodeParent != defaultParent)
			{
				// Don't generate an edge for the first node
				graph.insertEdge(defaultParent, null, '', nodeParent, nodeVertex, freeMindEdgeStyle);
			}
			
			cells.push(nodeVertex);
			// Insert child nodes, on correct positions
			var childNumber = 0;
			
			for (var i = 0; i < node.childNodes.length; i++)
			{
				var childNode = node.childNodes[i];
				
				if (childNode.nodeName == 'node')
				{
					var childX = x + nodeVertex.geometry.width + defaultHorizontalSpaceBetweenVertex;
					var childY = y + (defaultHeight + defaultVerticalSpaceBetweenVertex) * childNumber;
					childNumber += childNode.maxChilds == 0 ? 1 : childNode.maxChilds;
					processFreeMindNode(childNode, nodeVertex, childX, childY);
				}
			}
		}
		// Makes the import one undoable edit
		graph.getModel().beginUpdate();
		try
		{
			// Gets point for free space in the graph for insert
			var pt = graph.getFreeInsertPoint();
			var freeMindDOM = mxUtils.parseXml(data);
			var freeMindDOMchilds = freeMindDOM.children[0];
			// Transverse the childs, and generate relevant input 
			for (var i = 0; i < freeMindDOMchilds.childNodes.length; i++)
			{
				if (freeMindDOMchilds.childNodes[i].nodeName == 'node')
				{
					generatePreprocessingNodeInfo(freeMindDOMchilds.childNodes[i]);
				}
			}
			
			// Generate the nodes
			for (var i = 0; i < freeMindDOMchilds.childNodes.length; i++)
			{
				if (freeMindDOMchilds.childNodes[i].nodeName == 'node')
				{
					processFreeMindNode(freeMindDOMchilds.childNodes[i], defaultParent, pt.x, pt.y);
				}
			}
			// Applies current styles to new cells (might not be needed)
			graph.fireEvent(new mxEventObject('cellsInserted', 'cells', cells));
		}
		finally
		{
			graph.getModel().endUpdate();
		}
		// Selects new cells and scrolls into view
		graph.setSelectionCells(cells);
		graph.scrollCellToVisible(graph.getSelectionCell());
	};
	// Adds action
	ui.actions.addAction('importFreemind...', function()
	{
		// Only modern browsers for now. We'll move the import
		// code above to the main codebase later
		if (Graph.fileSupport)
		{
			if (ui.impFMFileInputElt == null) 
			{
				var input = document.createElement('input');
				input.setAttribute('type', 'file');
	
				mxEvent.addListener(input, 'change', function()
				{
					if (input.files != null)
					{
						// Only one file for now...
						var reader = new FileReader();
	
						reader.onload = function(e)
						{
							importFreemindData(e.target.result);
						};
	
						reader.readAsText(input.files[0]);
						
			    		// Resets input to force change event for same file (type reset required for IE)
						input.type = '';
						input.type = 'file';
			    		input.value = '';
					}
				});
				
				input.style.display = 'none';
				document.body.appendChild(input);
				ui.impFMFileInputElt = input;
			}
			
			ui.impFMFileInputElt.click();
		}
	});
	// Adds menu
	ui.menubar.addMenu('Import', function(menu, parent)
	{
		ui.menus.addMenuItem(menu, 'importFreemind');
	});
	// Moves import menu to before help menu
	ui.menubar.container.insertBefore(ui.menubar.container.lastChild,
			ui.menubar.container.lastChild.previousSibling.previousSibling.previousSibling);
});