diff --git a/mindplot/src/main/javascript/layout/OriginalLayout.js b/mindplot/src/main/javascript/layout/OriginalLayout.js index f630b1d0..2c0af97c 100644 --- a/mindplot/src/main/javascript/layout/OriginalLayout.js +++ b/mindplot/src/main/javascript/layout/OriginalLayout.js @@ -147,12 +147,30 @@ mindplot.layout.OriginalLayout = new Class({ }, _shiftBranches: function(node, heightById) { - var branchesToShift = this._treeSet.getBranchesInVerticalDirection(node, node.getFreeDisplacement().y); + var shiftedBranches = [node]; + var siblingsToShift = this._treeSet.getSiblingsInVerticalDirection(node, node.getFreeDisplacement().y); var last = node; + siblingsToShift.forEach(function(sibling) { + var overlappingOccurs = shiftedBranches.some(function(shiftedBranch) { + return this._branchesOverlap(shiftedBranch, sibling, heightById); + }, this); + + if (!sibling.isFree() || overlappingOccurs) { + this._treeSet.shiftBranchPosition(sibling, 0, node.getFreeDisplacement().y); + shiftedBranches.push(sibling); + } + }, this); + + var branchesToShift = this._treeSet.getBranchesInVerticalDirection(node, node.getFreeDisplacement().y); branchesToShift.forEach(function(branch) { - if (this._branchesOverlap(branch, last, heightById)) { + var overlappingOccurs = shiftedBranches.some(function(shiftedBranch) { + return this._branchesOverlap(shiftedBranch, branch, heightById); + }, this); + + if (overlappingOccurs) { this._treeSet.shiftBranchPosition(branch, 0, node.getFreeDisplacement().y); + shiftedBranches.push(branch); } last = branch; },this); diff --git a/mindplot/src/main/javascript/layout/RootedTreeSet.js b/mindplot/src/main/javascript/layout/RootedTreeSet.js index e7ab4594..1dac067a 100644 --- a/mindplot/src/main/javascript/layout/RootedTreeSet.js +++ b/mindplot/src/main/javascript/layout/RootedTreeSet.js @@ -232,12 +232,20 @@ mindplot.layout.RootedTreeSet = new Class({ }.bind(this)); }, - getBranchesInVerticalDirection: function(node, yOffset) { + getSiblingsInVerticalDirection: function(node, yOffset) { // siblings with lower or higher order, depending on the direction of the offset var siblings = this.getSiblings(node).filter(function(sibling) { return yOffset < 0 ? sibling.getOrder() < node.getOrder() : sibling.getOrder() > node.getOrder(); }); + if (yOffset < 0 ) { + siblings.reverse(); + } + + return siblings; + }, + + getBranchesInVerticalDirection: function(node, yOffset) { // direct descendants of the root that do not contain the node and are on the same side // and on the direction of the offset var rootNode = this.getRootNode(node); @@ -252,7 +260,7 @@ mindplot.layout.RootedTreeSet = new Class({ return sameSide && sameDirection; }, this); - return siblings.combine(rootDescendants); + return rootDescendants; } }); diff --git a/mindplot/src/test/javascript/static/layout.html b/mindplot/src/test/javascript/static/layout.html index 2e979c7d..cb494534 100644 --- a/mindplot/src/test/javascript/static/layout.html +++ b/mindplot/src/test/javascript/static/layout.html @@ -155,6 +155,11 @@
+ +

testsiblingOverlappingBug:

+
+
+
diff --git a/mindplot/src/test/javascript/static/test/FreeTestSuite.js b/mindplot/src/test/javascript/static/test/FreeTestSuite.js index b85bd48a..1b90c87c 100644 --- a/mindplot/src/test/javascript/static/test/FreeTestSuite.js +++ b/mindplot/src/test/javascript/static/test/FreeTestSuite.js @@ -24,6 +24,7 @@ mindplot.layout.FreeTestSuite = new Class({ this.testFreePosition(); this.testFreePredict(); this.testReconnectFreeNode(); + this.siblingOverlappingBug(); }, testFreePosition: function() { @@ -264,6 +265,37 @@ mindplot.layout.FreeTestSuite = new Class({ console.log("OK!\n\n"); }, + siblingOverlappingBug: function() { + console.log("siblingOverlappingBug:"); + var position = {x:0,y:0}; + var manager = new mindplot.layout.LayoutManager(0, mindplot.layout.TestSuite.ROOT_NODE_SIZE); + + // Prepare a sample graph ... + manager.addNode(1, mindplot.layout.TestSuite.NODE_SIZE, position).connectNode(0,1,0); + manager.addNode(2, mindplot.layout.TestSuite.NODE_SIZE, position).connectNode(1,2,0); + manager.addNode(3, mindplot.layout.TestSuite.NODE_SIZE, position).connectNode(1,3,1); + manager.addNode(4, mindplot.layout.TestSuite.NODE_SIZE, position).connectNode(1,4,2); + manager.addNode(5, mindplot.layout.TestSuite.NODE_SIZE, position).connectNode(1,5,3); + manager.addNode(6, mindplot.layout.TestSuite.NODE_SIZE, position).connectNode(1,6,4); + manager.addNode(7, mindplot.layout.TestSuite.NODE_SIZE, position).connectNode(1,7,5); + manager.addNode(8, mindplot.layout.TestSuite.NODE_SIZE, position).connectNode(1,8,6); + manager.addNode(9, mindplot.layout.TestSuite.NODE_SIZE, position).connectNode(0,9,4); + manager.layout(); + manager.plot("siblingOverlappingBug1", {width:800, height:600}); + + console.log("\tmove node 2"); + manager.moveNode(2, {x:250, y: -30}); + manager.layout(); + manager.plot("siblingOverlappingBug2", {width:800, height:600}); + this._assertFreePosition(manager, 2, {x:250, y: -30}); + + console.log("\tmove node 7"); + manager.moveNode(7, {x:250, y: 100}); + manager.layout(); + manager.plot("siblingOverlappingBug3", {width:800, height:600}); + this._assertFreePosition(manager, 7, {x:250, y: 100}); + }, + _assertFreePosition: function(manager, id, position) { if (id != null && position.x != null && position.y != null) { var node = manager.find(id);