From d4de03d3739aa2dd26290506ba8275925c659a0a Mon Sep 17 00:00:00 2001 From: Pablo Luna Date: Fri, 8 Apr 2011 15:31:40 +0100 Subject: [PATCH] working on Freemind layout algorithm --- mindplot/pom.xml | 3 + mindplot/src/main/javascript/CentralTopic.js | 2 +- .../src/main/javascript/CentralTopicBoard.js | 2 +- .../src/main/javascript/ConnectionLine.js | 2 +- .../main/javascript/DesignerActionRunner.js | 4 - mindplot/src/main/javascript/DragTopic.js | 2 +- mindplot/src/main/javascript/MainTopic.js | 27 +-- mindplot/src/main/javascript/Mindmap.js | 8 +- mindplot/src/main/javascript/NodeModel.js | 32 ++- mindplot/src/main/javascript/Topic.js | 18 +- .../javascript/XMLMindmapSerializer_Pela.js | 9 +- .../javascript/commands/AddTopicCommand.js | 2 + .../commands/freeMind/DragTopicCommand.js | 60 ++++++ .../layoutManagers/BaseLayoutManager.js | 21 +- .../layoutManagers/FreeMindLayoutManager.js | 134 ++++++++++--- .../layoutManagers/OriginalLayoutManager.js | 2 +- .../javascript/layoutManagers/boards/Board.js | 14 +- .../boards/freeMindBoards/Board.js | 185 ++++++++++++++---- .../boards/freeMindBoards/Entry.js | 86 ++++++-- .../controller/ExportController.java | 3 +- 20 files changed, 472 insertions(+), 144 deletions(-) create mode 100644 mindplot/src/main/javascript/commands/freeMind/DragTopicCommand.js diff --git a/mindplot/pom.xml b/mindplot/pom.xml index ef00d8ad..882d68b6 100644 --- a/mindplot/pom.xml +++ b/mindplot/pom.xml @@ -124,6 +124,8 @@ files="commands/AddRelationshipCommand.js"/> + commands/RemoveNoteFromTopicCommand-min.js commands/AddRelationshipCommand-min.js commands/MoveControlPointCommand-min.js + commands/freeMind/DragTopicCommand-min.js layoutManagers/boards/Board-min.js layoutManagers/boards/freeMindBoards/Board-min.js diff --git a/mindplot/src/main/javascript/CentralTopic.js b/mindplot/src/main/javascript/CentralTopic.js index 628f5802..b599f2b4 100644 --- a/mindplot/src/main/javascript/CentralTopic.js +++ b/mindplot/src/main/javascript/CentralTopic.js @@ -87,7 +87,7 @@ mindplot.CentralTopic.prototype.updateTopicShape = function() { }; -mindplot.CentralTopic.prototype._updatePositionOnChangeSize = function(oldSize, newSize) { +mindplot.CentralTopic.prototype._updatePositionOnChangeSize = function(oldSize, newSize, updatePosition) { // Center main topic ... var zeroPoint = new core.Point(0, 0); diff --git a/mindplot/src/main/javascript/CentralTopicBoard.js b/mindplot/src/main/javascript/CentralTopicBoard.js index 3439c4bd..bc0b4ce6 100644 --- a/mindplot/src/main/javascript/CentralTopicBoard.js +++ b/mindplot/src/main/javascript/CentralTopicBoard.js @@ -103,7 +103,7 @@ mindplot.CentralTopicBoard.prototype.addBranch = function(topic) board.update(entry); }; -mindplot.CentralTopicBoard.prototype.updateChildrenPosition = function(topic, xOffset) +mindplot.CentralTopicBoard.prototype.updateChildrenPosition = function(topic, xOffset, modifiedTopics) { var board = this._rightBoard; var oldReferencePosition = board.getReferencePoint(); diff --git a/mindplot/src/main/javascript/ConnectionLine.js b/mindplot/src/main/javascript/ConnectionLine.js index fd28c8b4..55622b7f 100644 --- a/mindplot/src/main/javascript/ConnectionLine.js +++ b/mindplot/src/main/javascript/ConnectionLine.js @@ -141,7 +141,7 @@ mindplot.ConnectionLine.prototype._positionateConnector = function(targetTopic) y = y - offset; var connector = targetTopic.getShrinkConnector(); - if (targetPosition.x >= 0) + if (Math.sign(targetPosition.x) > 0) { var x = targetTopicSize.width; connector.setPosition(x, y); diff --git a/mindplot/src/main/javascript/DesignerActionRunner.js b/mindplot/src/main/javascript/DesignerActionRunner.js index d41116d3..c41ebdcc 100644 --- a/mindplot/src/main/javascript/DesignerActionRunner.js +++ b/mindplot/src/main/javascript/DesignerActionRunner.js @@ -97,10 +97,6 @@ mindplot.CommandContext = new Class({ core.assert(model, "model can not be null"); var topic = this._designer._nodeModelToNodeGraph(model, isVisible); - // @todo: Is this required ? - var designer = this._designer; - designer.onObjectFocusEvent.attempt(topic, designer); - return topic; }, createModel:function() diff --git a/mindplot/src/main/javascript/DragTopic.js b/mindplot/src/main/javascript/DragTopic.js index 6181ee53..b0ab32e2 100644 --- a/mindplot/src/main/javascript/DragTopic.js +++ b/mindplot/src/main/javascript/DragTopic.js @@ -207,7 +207,7 @@ mindplot.DragTopic.prototype.updateDraggedTopic = function(workspace) command = new mindplot.commands.DragTopicCommand(topicId, dragPosition); command.setPosition(dragPosition); } - actionRunner.execute(command) + actionRunner.execute(command); }; mindplot.DragTopic.prototype.setBoardPosition = function(point) diff --git a/mindplot/src/main/javascript/MainTopic.js b/mindplot/src/main/javascript/MainTopic.js index cebae842..0dcd5d91 100644 --- a/mindplot/src/main/javascript/MainTopic.js +++ b/mindplot/src/main/javascript/MainTopic.js @@ -175,20 +175,25 @@ mindplot.MainTopic.prototype.getTopicType = function() }; -mindplot.MainTopic.prototype._updatePositionOnChangeSize = function(oldSize, newSize) { +mindplot.MainTopic.prototype._updatePositionOnChangeSize = function(oldSize, newSize, updatePosition) { - var xOffset = (newSize.width - oldSize.width) / 2; - var pos = this.getPosition(); - if (core.Utils.isDefined(pos)) - { - if (pos.x > 0) + if(!updatePosition && this.getModel().getFinalPosition()){ + this.setPosition(this.getModel().getFinalPosition(), false); + } + else{ + var xOffset = Math.round((newSize.width - oldSize.width) / 2); + var pos = this.getPosition(); + if (core.Utils.isDefined(pos)) { - pos.x = pos.x + xOffset; - } else - { - pos.x = pos.x - xOffset; + if (pos.x > 0) + { + pos.x = pos.x + xOffset; + } else + { + pos.x = pos.x - xOffset; + } + this.setPosition(pos); } - this.setPosition(pos); } }; diff --git a/mindplot/src/main/javascript/Mindmap.js b/mindplot/src/main/javascript/Mindmap.js index c3e4b2ae..e6a8cdce 100644 --- a/mindplot/src/main/javascript/Mindmap.js +++ b/mindplot/src/main/javascript/Mindmap.js @@ -126,16 +126,16 @@ mindplot.Mindmap.prototype.hasAlreadyAdded = function(node) } }; -mindplot.Mindmap.prototype.createNode = function(type) +mindplot.Mindmap.prototype.createNode = function(type, id) { core.assert(type, "node type can not be null"); - return this._createNode(type); + return this._createNode(type, id); }; -mindplot.Mindmap.prototype._createNode = function(type) +mindplot.Mindmap.prototype._createNode = function(type, id) { core.assert(type, 'Node type must be specified.'); - var result = new mindplot.NodeModel(type, this); + var result = new mindplot.NodeModel(type, this, id); return result; }; diff --git a/mindplot/src/main/javascript/NodeModel.js b/mindplot/src/main/javascript/NodeModel.js index 2fbf1f06..5bf155b4 100644 --- a/mindplot/src/main/javascript/NodeModel.js +++ b/mindplot/src/main/javascript/NodeModel.js @@ -16,7 +16,7 @@ * limitations under the License. */ -mindplot.NodeModel = function(type, mindmap) +mindplot.NodeModel = function(type, mindmap, id) { core.assert(type, 'Node type can not be null'); core.assert(mindmap, 'mindmap can not be null'); @@ -29,7 +29,14 @@ mindplot.NodeModel = function(type, mindmap) this._notes = []; this._size = {width:50,height:20}; this._position = null; - this._id = mindplot.NodeModel._nextUUID(); + if(core.Utils.isDefined(id)){ + if(!mindplot.NodeModel._uuid || id>mindplot.NodeModel._uuid){ + mindplot.NodeModel._uuid = id; + } + this._id = id; + } else { + this._id = mindplot.NodeModel._nextUUID(); + } this._mindmap = mindmap; this._text = null; this._shapeType = null; @@ -95,6 +102,9 @@ mindplot.NodeModel.prototype.getId = function() mindplot.NodeModel.prototype.setId = function(id) { this._id = id; + if(mindplot.NodeModel._uuid0){ + var refPos = node.getPosition(); + for( var i = 0 ; i< children.length ; i++){ + var child = children[i]; + this._changeChildrenSide(child); + var childPos = child.getPosition(); + var oldPos=childPos.clone(); + childPos.x = newPos.x +(childPos.x - refPos.x)*-1; + childPos.y = newPos.y +(childPos.y - refPos.y); + child.setPosition(childPos, false); + if(modifiedTopics.set){ + var key = node.getId(); + if(modifiedTopics.hasKey(key)){ + childPos = this._modifiedTopics.get(key).originalPos; + } + this._modifiedTopics.set(key,{originalPos:oldPos, newPos:childPos}); + } + } + } + }, _mouseUpListener:function(event, node){ var id = node.getId(); - console.log("up on node: "+id); - + var screen = this._designer.getWorkSpace().getScreenManager(); // Remove all the events. screen.removeEventListener('mousemove', this._mouseMoveListenerInstance); @@ -101,19 +157,16 @@ mindplot.layoutManagers.FreeMindLayoutManager = mindplot.layoutManagers.BaseLayo this._designer.getWorkSpace().enableWorkspaceEvents(true); + this._command.setModifiedTopics(this._modifiedTopics); + var actionRunner = mindplot.DesignerActionRunner.getInstance(); + actionRunner.execute(this._command); + this._command=null; + this._modifiedTopics=null; + // var topicId = draggedTopic.getId(); // var command = new mindplot.commands.DragTopicCommand(topicId); }, - _updateNodePos:function(node, delta){ - var pos = node.getPosition(); - node.setPosition(new core.Point(pos.x-delta.x, pos.y-delta.y)); - /*var children = node._getChildren(); - for (var i = 0; i < children.length; i++) - { - this._updateNodePos(children[i],delta); - }*/ - }, getClassName:function(){ return mindplot.layoutManagers.FreeMindLayoutManager.NAME; }, @@ -122,6 +175,33 @@ mindplot.layoutManagers.FreeMindLayoutManager = mindplot.layoutManagers.BaseLayo }, _createCentralTopicBoard:function(node){ return new mindplot.layoutManagers.boards.freeMindBoards.CentralTopicBoard(node, this); + }, + _updateParentBoard:function(node, modifiedTopics){ + var parent = node.getParent(); + if(!this._isCentralTopic(parent)){ + var parentBoard = this.getTopicBoardForTopic(parent.getParent()); + var result = parentBoard.findNodeEntryIndex(parent); + var parentEntry = result.table[result.index]; + var board = this.getTopicBoardForTopic(parent); + var table = board._getTableForNode(null); + if(table.length>0){ + var firstChild = table[0]; + var marginTop = parentEntry.getPosition()-(firstChild.getPosition()-firstChild.getTotalMarginTop()); + parentBoard.setNodeChildrenMarginTop(parentEntry,marginTop); + var lastChild = table[table.length-1]; + var marginBottom = (lastChild.getPosition()+lastChild.getTotalMarginBottom())-parentEntry.getPosition(); + parentBoard.setNodeChildrenMarginBottom(parentEntry,marginBottom); + parentBoard._updateTable(result.index, result.table, modifiedTopics, false); + } + this._updateParentBoard(parent, modifiedTopics); + } + }, + _updateChildrenBoards:function(node, delta, modifiedTopics){ + var board = this.getTopicBoardForTopic(node); + var topics = board._getTableForNode(null); + for(var i=0; i0){ + var selectedNode = this._layoutManager.getDesigner().getSelectedNodes()[0]; + if(selectedNode.getParent()!= null && node.getParent().getId() == selectedNode.getParent().getId() && !this._layoutManager._isCentralTopic(node.getParent())){ + //creating a sibling - Lets put the new node below the selected node. + var parentBoard = this._layoutManager.getTopicBoardForTopic(selectedNode.getParent()); + var selectedNodeResult = parentBoard.findNodeEntryIndex(selectedNode); + var selectedNodeEntry = selectedNodeResult.table[selectedNodeResult.index]; + entry.setPosition(null, selectedNodeEntry.getPosition()+selectedNodeEntry.getTotalMarginBottom() + entry.getMarginTop()); + result.index = selectedNodeResult.index+1; + } else if(node.getParent().getId() == selectedNode.getId()){ + //creating a child node - Lest put the new node as the last child. + var selectedNodeBoard = this._layoutManager.getTopicBoardForTopic(selectedNode); + var table = selectedNodeBoard._getTableForNode(node); + if(table.length>0){ + //if no children use the position set by Entry initializer. Otherwise place as last child + var lastChild = table[table.length-1]; + entry.setPosition(null, lastChild.getPosition()+lastChild.getTotalMarginBottom() + entry.getMarginTop()); + } + result.index = table.length; + } + } + this._addEntry(entry, result.table, result.index); + if(pos){ + if(result.index>0){ + var prevEntry =result.table[result.index-1]; + entry.setMarginTop(pos.y-(prevEntry.getPosition() + prevEntry.getTotalMarginBottom())); + } + else if(result.table.length>1){ + var nextEntry = result.table[1]; + nextEntry.setMarginTop((nextEntry.getPosition() - nextEntry.getTotalMarginTop())-pos.y); + } + var parent = node.getParent(); + if(!this._layoutManager._isCentralTopic(parent) && (result.index == 0 || result.index==result.table.length-1)){ + var board = this._layoutManager.getTopicBoardForTopic(parent.getParent()); + var res2 = board.findNodeEntryIndex(parent); + var parentEntry = res2.table[res2.index]; + var totalMarginTop = parentEntry.getTotalMarginTop(); + var totalMarginBottom = parentEntry.getTotalMarginBottom(); + var parentPosition = parentEntry.getPosition(); + if(result.index==0 && pos.y < parentPosition){ + var childrenMarginTop = parentEntry.getPosition()-(pos.y-entry.getTotalMarginTop()); + parentEntry.setMarginTop(totalMarginTop-childrenMarginTop); + }else if(result.index==result.table.length-1 && pos.y>parentPosition){ + var childrenMarginBottom = (pos.y+entry.getTotalMarginBottom())-parentEntry.getPosition(); + parentEntry.setMarginBottom(totalMarginBottom - childrenMarginBottom); + } + } + } + this._updateTable(result.index, result.table,modifiedTopics, false); + this._layoutManager._updateParentBoard(node, modifiedTopics); }, - _insertNewEntry:function(node, table, index){ - var entry = new mindplot.layoutManagers.boards.freeMindBoards.Entry(node); - table.splice(index, 0, entry); - this._updateTable(index, table); - }, - _removeEntry:function(node, table, index){ + _removeEntry:function(node, table, index, modifiedTopics){ table.splice(index, 1); - this._updateTable(index, table); + this._updateTable(index, table, modifiedTopics, false); }, - _updateTable:function(index, table){ + _addEntry:function(entry, table, index){ + table.splice(index, 0, entry); + }, + _updateTable:function(index, table, modifiedTopics, updateParents){ var i = index; if(index >= table.length){ i = table.length -1; } - - var modifiedTopics = []; var delta = null; //check from index to 0; if(i>0){ var entry = table[i]; var prevEntry = table[i-1]; - var marginTop = entry.getPosition() + entry.getMarginTop(); - var marginBottom = prevEntry.getPosition() - prevEntry.getMarginBottom(); - if(marginTop>marginBottom){ - delta = marginBottom - marginTop; + + var margin = entry.getTotalMarginTop() + prevEntry.getTotalMarginBottom(); + var distance = Math.abs(prevEntry.getPosition() - entry.getPosition()); + if(distance!=margin){ + delta = (distance - margin)*Math.sign(prevEntry.getPosition() - entry.getPosition()); i--; while(i >= 0){ - this._moveTopic(table[i], delta, modifiedTopics); + this._updateEntryPos(table[i], new core.Point(null, delta), modifiedTopics, updateParents); i--; } } @@ -72,27 +124,25 @@ mindplot.layoutManagers.boards.freeMindBoards.Board = mindplot.layoutManagers.bo if( imarginBottom){ - delta = marginTop-marginBottom; + var margin = entry.getTotalMarginBottom() + nextEntry.getTotalMarginTop(); + var distance = Math.abs(entry.getPosition() - nextEntry.getPosition()); + if(distance!=margin){ + delta = (distance - margin)*Math.sign(nextEntry.getPosition() - entry.getPosition()); i++; while(i position){ + break; + } + } + return {index:i, table:table}; + }, + setNodeMarginTop:function(entry, delta){ var marginTop = entry.getMarginTop()-delta.y; entry.setMarginTop(marginTop); + }, + setNodeMarginBottom:function(entry, delta){ + var marginBottom = entry.getMarginBottom()-delta.y; + entry.setMarginBottom(marginBottom); + }, + setNodeChildrenMarginTop:function(entry, delta){ + var marginTop = entry.getChildrenMarginTop()-delta.y; + entry.setChildrenMarginTop(delta); + }, + setNodeChildrenMarginBottom:function(entry, delta){ + var marginBottom = entry.getChildrenMarginBottom()-delta.y; + entry.setChildrenMarginBottom(delta); + }, + updateEntry:function(node, delta, modifiedTopics){ + var result = this.findNodeEntryIndex(node); + if(result.index < result.table.length){ + var entry = result.table[result.index]; + if(result.index!=0) + this.setNodeMarginTop(entry, delta); + this._updateEntryPos(entry, delta, modifiedTopics, false); + this._updateTable(result.index, result.table, modifiedTopics, false); + this._layoutManager._updateParentBoard(entry.getNode(), modifiedTopics); + } + }, + _updateEntryPos:function(entry, delta, modifiedTopics, updateParents){ + var pos = entry.getNode().getPosition().clone(); + var newPos = new core.Point(pos.x-(delta.x==null?0:delta.x), pos.y-delta.y); + entry.setPosition(newPos.x, newPos.y); + this._layoutManager._updateChildrenBoards(entry.getNode(), delta, modifiedTopics); +// if(updateParents) +// this._layoutManager._updateParentBoard(entry.getNode(), modifiedTopics); + if(modifiedTopics.set){ + var key = entry.getId(); + if(modifiedTopics.hasKey(key)){ + pos = modifiedTopics.get(key).originalPos; + } + modifiedTopics.set(key,{originalPos:pos, newPos:newPos}); + } } }); \ No newline at end of file diff --git a/mindplot/src/main/javascript/layoutManagers/boards/freeMindBoards/Entry.js b/mindplot/src/main/javascript/layoutManagers/boards/freeMindBoards/Entry.js index d18a8e23..ff6acd78 100644 --- a/mindplot/src/main/javascript/layoutManagers/boards/freeMindBoards/Entry.js +++ b/mindplot/src/main/javascript/layoutManagers/boards/freeMindBoards/Entry.js @@ -1,43 +1,91 @@ mindplot.layoutManagers.boards.freeMindBoards.Entry = new Class({ - initialize:function(node){ + initialize:function(node, useFinalPosition){ this._node = node; this._DEFAULT_X_GAP = 30; - var pos = node.getPosition(); - if(!pos){ - var parent = node.getParent(); - pos = parent.getPosition().clone(); - var pwidth = parent.getSize().width; - var width = node.getSize().width; - pos.x = pos.x + Math.sign(pos.x) * (this._DEFAULT_X_GAP + pwidth/2 + width/2); - node.setPosition(pos, false); + var pos = node.getModel().getFinalPosition(); + if(useFinalPosition && pos){ + this.setPosition(pos.x, pos.y); + } + else{ + pos = node.getPosition(); + if(!pos){ + var parent = node.getParent(); + pos = parent.getPosition().clone(); + var pwidth = parent.getSize().width; + var width = node.getSize().width; + pos.x = pos.x + Math.sign(pos.x) * (this._DEFAULT_X_GAP + pwidth/2 + width/2); + node.setPosition(pos, false); + + } } this._position = pos.y; - var height = node.getSize().height; this._DEFAULT_GAP = 10; - this._marginTop = this._DEFAULT_GAP + height/2; - this._marginBottom = this._DEFAULT_GAP + height/2; + var height = this.getNode().getSize().height; + this._minimalMargin = this._DEFAULT_GAP + height/2; + this._marginTop = this._minimalMargin; + this._marginBottom = this._minimalMargin; + this._marginTopChildren=0; + this._marginBottomChildren=0; }, getNode:function(){ return this._node; }, + getId:function(){ + return this.getNode().getId(); + }, getPosition:function(){ return this._position; }, - setPosition:function(pos){ - var position = this._node.getPosition(); - position.y = pos; - this._node.setPosition(position); - this._position = pos; + setPosition:function(x,y){ + var position = this._node.getPosition().clone(); + position.y = y; + if(null != x){ + position.x = x; + } + + this._node.setPosition(position, false); + this._position = y; }, getMarginTop:function(){ return this._marginTop; }, setMarginTop:function(value){ - if(value >= this._DEFAULT_GAP){ + if(value >= this._minimalMargin){ this._marginTop = value; } }, + setMarginBottom:function(value){ + if(value >= this._minimalMargin){ + this._marginBottom = value; + } + }, getMarginBottom:function(){ - return this._marginTop; + return this._marginBottom; + }, + getChildrenMarginTop:function(){ + return this._marginTopChildren; + }, + setChildrenMarginTop:function(value){ + if(value >= this._minimalMargin){ + this._marginTopChildren = value - this._minimalMargin; + }else{ + this._marginTopChildren=0; + } + }, + setChildrenMarginBottom:function(value){ + if(value >= this._minimalMargin){ + this._marginBottomChildren = value - this._minimalMargin; + }else{ + this._marginBottomChildren=0; + } + }, + getChildrenMarginBottom:function(){ + return this._marginBottomChildren; + }, + getTotalMarginTop:function(){ + return this._marginTopChildren+this._marginTop; + }, + getTotalMarginBottom:function(){ + return this._marginBottomChildren + this._marginBottom; } }); \ No newline at end of file diff --git a/wise-webapp/src/main/java/com/wisemapping/controller/ExportController.java b/wise-webapp/src/main/java/com/wisemapping/controller/ExportController.java index bbff318f..5896e93b 100644 --- a/wise-webapp/src/main/java/com/wisemapping/controller/ExportController.java +++ b/wise-webapp/src/main/java/com/wisemapping/controller/ExportController.java @@ -64,11 +64,11 @@ public class ExportController extends BaseMultiActionController { final String mapIdStr = request.getParameter(MAP_ID_PARAMETER); if (mapIdStr != null) { + final String mapSvg = request.getParameter(MAP_SVG_PARAMETER); try { int mindmapId = Integer.parseInt(mapIdStr); - final String mapSvg = request.getParameter(MAP_SVG_PARAMETER); logger.debug("SVG Map to export:"+mapSvg); if(mapSvg==null || mapSvg.isEmpty()) { @@ -116,6 +116,7 @@ public class ExportController extends BaseMultiActionController { } catch (Throwable e) { logger.error("Unexpexted error during export process", e); response.setStatus(HttpServletResponse.SC_NOT_FOUND); + logger.error("map: "+mapSvg); } } else { logger.warn("mapIdStr is null.Image could not be imported. UserAgent:" + request.getHeaders(UserAgent.USER_AGENT_HEADER));