01c7f7d55d
Former-commit-id: 89c43b4cd8
169 lines
No EOL
5.8 KiB
JavaScript
169 lines
No EOL
5.8 KiB
JavaScript
/**
|
|
* 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 freeMindParser = new DOMParser();
|
|
freeMindDOM = freeMindParser.parseFromString(data, "text/xml");
|
|
|
|
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 && !mxClient.IS_IE && !mxClient.IS_IE11)
|
|
{
|
|
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]);
|
|
}
|
|
});
|
|
|
|
input.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);
|
|
}); |