Files
wisemapping-open-source/mindplot/src/main/javascript/layout/SymmetricSorter.js

236 lines
9.5 KiB
JavaScript
Raw Normal View History

2012-01-09 23:50:52 -03:00
/*
2012-10-04 20:48:01 -03:00
* Copyright [2012] [wisemapping]
2012-01-09 23:50:52 -03:00
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
2012-01-14 14:20:59 -03:00
mindplot.layout.SymmetricSorter = new Class({
2012-07-09 18:52:59 -03:00
Extends:mindplot.layout.AbstractBasicSorter,
initialize:function () {
},
2012-08-17 17:32:57 -03:00
/**
* Predict the order and position of a dragged node.
*
* @param graph The tree set
* @param parent The parent of the node
* @param node The node
* @param position The position of the drag
* @param free Free drag or not
* @return {*}
*/
2012-07-09 18:52:59 -03:00
predict:function (graph, parent, node, position, free) {
2012-08-17 17:32:57 -03:00
var self = this;
var rootNode = graph.getRootNode(parent);
// If its a free node...
if (free) {
$assert($defined(position), "position cannot be null for predict in free positioning");
$assert($defined(node), "node cannot be null for predict in free positioning");
var direction = this._getRelativeDirection(rootNode.getPosition(), parent.getPosition());
2012-07-09 18:52:59 -03:00
var limitXPos = parent.getPosition().x + direction * (parent.getSize().width / 2 + node.getSize().width / 2 + mindplot.layout.SymmetricSorter.INTERNODE_HORIZONTAL_PADDING);
var xPos = direction > 0 ?
(position.x >= limitXPos ? position.x : limitXPos) :
2012-07-09 18:52:59 -03:00
(position.x <= limitXPos ? position.x : limitXPos);
2012-07-09 18:52:59 -03:00
return [0, {x:xPos, y:position.y}];
}
2012-08-17 17:32:57 -03:00
// Its not a dragged node (it is being added)
if (!node) {
var parentDirection = self._getRelativeDirection(rootNode.getPosition(), parent.getPosition());
var position = {
x:parent.getPosition().x + parentDirection * (parent.getSize().width + mindplot.layout.SymmetricSorter.INTERNODE_HORIZONTAL_PADDING),
y:parent.getPosition().y
};
return [graph.getChildren(parent).length, position];
}
// If it is a dragged node...
2012-08-17 17:32:57 -03:00
$assert($defined(position), "position cannot be null for predict in dragging");
var nodeDirection = this._getRelativeDirection(rootNode.getPosition(), node.getPosition());
var positionDirection = this._getRelativeDirection(rootNode.getPosition(), position);
var siblings = graph.getSiblings(node);
// node has no siblings and its trying to reconnect to its own parent
var sameParent = parent == graph.getParent(node);
if (siblings.length == 0 && nodeDirection == positionDirection && sameParent) {
return [node.getOrder(), node.getPosition()];
}
2012-08-17 17:32:57 -03:00
var parentChildren = graph.getChildren(parent);
if (parentChildren.length == 0) {
// Fit as a child of the parent node...
var position = {
x:parent.getPosition().x + positionDirection * (parent.getSize().width + mindplot.layout.SymmetricSorter.INTERNODE_HORIZONTAL_PADDING),
2012-01-12 19:58:18 -03:00
y:parent.getPosition().y
2012-01-17 00:26:29 -03:00
};
2012-08-17 17:32:57 -03:00
return [0, position];
} else {
// Try to fit within ...
var result = null;
var last = parentChildren.getLast();
for (var i = 0; i < parentChildren.length; i++) {
2012-08-17 17:32:57 -03:00
var parentChild = parentChildren[i];
var nodeAfter = (i + 1) == parentChild.length ? null : parentChildren[i + 1];
2012-08-17 17:32:57 -03:00
// Fit at the bottom
if (!nodeAfter && position.y > parentChild.getPosition().y) {
var order = (graph.getParent(node) && graph.getParent(node).getId() == parent.getId()) ?
2012-08-17 17:32:57 -03:00
last.getOrder() : last.getOrder() + 1;
var position = {
x:parentChild.getPosition().x,
y:parentChild.getPosition().y + parentChild.getSize().height + mindplot.layout.SymmetricSorter.INTERNODE_VERTICAL_PADDING * 2
2012-08-18 23:37:32 -03:00
};
2012-08-17 17:32:57 -03:00
return [order, position];
}
// Fit after this node
if (nodeAfter && position.y > parentChild.getPosition().y && position.y < nodeAfter.getPosition().y) {
if (nodeAfter.getId() == node.getId() || parentChild.getId() == node.getId()) {
2012-08-17 17:32:57 -03:00
return [node.getOrder(), node.getPosition()];
} else {
var order = position.y > node.getPosition().y ?
nodeAfter.getOrder() - 1 : parentChild.getOrder() + 1;
var position = {
x:parentChild.getPosition().x,
y:parentChild.getPosition().y + (nodeAfter.getPosition().y - parentChild.getPosition().y) / 2
2012-08-18 23:37:32 -03:00
};
2012-08-17 17:32:57 -03:00
return [order, position];
}
}
}
}
2012-08-17 17:32:57 -03:00
// Position wasn't below any node, so it must be fitted above the first
var first = parentChildren[0];
var position = {
2012-08-17 17:32:57 -03:00
x:first.getPosition().x,
y:first.getPosition().y - first.getSize().height - mindplot.layout.SymmetricSorter.INTERNODE_VERTICAL_PADDING * 2
};
return [0, position];
},
2012-07-09 18:52:59 -03:00
insert:function (treeSet, parent, child, order) {
2011-12-11 23:47:01 -03:00
var children = this._getSortedChildren(treeSet, parent);
$assert(order <= children.length, "Order must be continues and can not have holes. Order:" + order);
// Shift all the elements in one .
for (var i = order; i < children.length; i++) {
var node = children[i];
2011-12-11 23:47:01 -03:00
node.setOrder(i + 1);
}
child.setOrder(order);
},
2012-07-09 18:52:59 -03:00
detach:function (treeSet, node) {
2011-12-11 23:47:01 -03:00
var parent = treeSet.getParent(node);
var children = this._getSortedChildren(treeSet, parent);
var order = node.getOrder();
$assert(children[order] === node, "Node seems not to be in the right position");
// Shift all the nodes ...
for (var i = node.getOrder() + 1; i < children.length; i++) {
var child = children[i];
child.setOrder(child.getOrder() - 1);
}
node.setOrder(0);
},
2012-07-09 18:52:59 -03:00
computeOffsets:function (treeSet, node) {
$assert(treeSet, "treeSet can no be null.");
$assert(node, "node can no be null.");
2011-12-11 23:47:01 -03:00
var children = this._getSortedChildren(treeSet, node);
// Compute heights ...
2012-01-11 19:47:00 -03:00
var heights = children.map(
2012-07-09 18:52:59 -03:00
function (child) {
return {id:child.getId(), order:child.getOrder(), position:child.getPosition(), width:child.getSize().width, height:this._computeChildrenHeight(treeSet, child)};
2012-01-11 19:47:00 -03:00
}, this).reverse();
// Compute the center of the branch ...
var totalHeight = 0;
2012-07-09 18:52:59 -03:00
heights.each(function (elem) {
totalHeight += elem.height;
});
var ysum = totalHeight / 2;
// Calculate the offsets ...
var result = {};
for (var i = 0; i < heights.length; i++) {
ysum = ysum - heights[i].height;
var childNode = treeSet.find(heights[i].id);
2012-07-09 18:52:59 -03:00
var direction = this.getChildDirection(treeSet, childNode);
2012-01-11 19:47:00 -03:00
var yOffset = ysum + heights[i].height / 2;
2012-01-17 00:26:29 -03:00
var xOffset = direction * (heights[i].width / 2 + node.getSize().width / 2 + mindplot.layout.SymmetricSorter.INTERNODE_HORIZONTAL_PADDING);
$assert(!isNaN(xOffset), "xOffset can not be null");
$assert(!isNaN(yOffset), "yOffset can not be null");
2012-07-09 18:52:59 -03:00
result[heights[i].id] = {x:xOffset, y:yOffset};
}
return result;
},
2012-07-09 18:52:59 -03:00
verify:function (treeSet, node) {
2012-01-11 19:47:00 -03:00
// Check that all is consistent ...
var children = this._getSortedChildren(treeSet, node);
for (var i = 0; i < children.length; i++) {
$assert(children[i].getOrder() == i, "missing order elements");
}
},
2012-07-09 18:52:59 -03:00
getChildDirection:function (treeSet, child) {
$assert(treeSet, "treeSet can no be null.");
$assert(treeSet.getParent(child), "This should not happen");
var result;
var rootNode = treeSet.getRootNode(child);
if (treeSet.getParent(child) == rootNode) {
// This is the case of a isolated child ... In this case, the directions is based on the root.
result = Math.sign(rootNode.getPosition().x);
} else {
// if this is not the case, honor the direction of the parent ...
var parent = treeSet.getParent(child);
var grandParent = treeSet.getParent(parent);
var sorter = grandParent.getSorter();
result = sorter.getChildDirection(treeSet, parent);
}
return result;
2012-01-26 13:07:45 -03:00
},
2012-07-09 18:52:59 -03:00
toString:function () {
return "Symmetric Sorter";
2012-03-06 18:01:56 -03:00
},
2012-07-09 18:52:59 -03:00
_getVerticalPadding:function () {
2012-03-06 18:01:56 -03:00
return mindplot.layout.SymmetricSorter.INTERNODE_VERTICAL_PADDING;
}
});
2012-01-14 14:20:59 -03:00
mindplot.layout.SymmetricSorter.INTERNODE_VERTICAL_PADDING = 5;
mindplot.layout.SymmetricSorter.INTERNODE_HORIZONTAL_PADDING = 30;