mirror of
https://bitbucket.org/wisemapping/wisemapping-open-source.git
synced 2024-09-12 07:10:07 +02:00
Close the first prototype of the new layout
This commit is contained in:
parent
a482c410a2
commit
9c41f0719c
36
mindplot/src/main/javascript/nlayout/ChangeEvent.js
Normal file
36
mindplot/src/main/javascript/nlayout/ChangeEvent.js
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
mindplot.nlayout.ChangeEvent = new Class({
|
||||||
|
initialize:function(id) {
|
||||||
|
$assert(!isNaN(id), "id can not be null");
|
||||||
|
this._id = id;
|
||||||
|
this._position = null;
|
||||||
|
this._order = null;
|
||||||
|
},
|
||||||
|
|
||||||
|
getId:function() {
|
||||||
|
return this._id;
|
||||||
|
},
|
||||||
|
|
||||||
|
getOrder: function() {
|
||||||
|
return this._order;
|
||||||
|
},
|
||||||
|
|
||||||
|
getPosition: function() {
|
||||||
|
return this._position;
|
||||||
|
},
|
||||||
|
|
||||||
|
setOrder: function(value) {
|
||||||
|
$assert(!isNaN(value), "value can not be null");
|
||||||
|
this._order = value;
|
||||||
|
},
|
||||||
|
|
||||||
|
setPosition: function(value) {
|
||||||
|
$assert(value, "value can not be null");
|
||||||
|
this._position = value;
|
||||||
|
},
|
||||||
|
|
||||||
|
toString: function() {
|
||||||
|
return "[order:" + this.getOrder() + ", position: {" + this.getPosition().x + "," + this.getPosition().y + "}]";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
@ -0,0 +1,23 @@
|
|||||||
|
mindplot.nlayout.ChildrenSorterStrategy = new Class({
|
||||||
|
initialize:function() {
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
predict:function(treeSet, parent, position) {
|
||||||
|
throw "Method must be implemented";
|
||||||
|
},
|
||||||
|
|
||||||
|
sorter: function(treeSet, parent, child, order) {
|
||||||
|
throw "Method must be implemented";
|
||||||
|
},
|
||||||
|
|
||||||
|
computeChildrenIdByHeights: function(treeSet, node) {
|
||||||
|
throw "Method must be implemented";
|
||||||
|
},
|
||||||
|
|
||||||
|
computeOffsets:function(treeSet, node) {
|
||||||
|
throw "Method must be implemented";
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
8
mindplot/src/main/javascript/nlayout/GridSorter.js
Normal file
8
mindplot/src/main/javascript/nlayout/GridSorter.js
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
mindplot.nlayout.GridSorter = new Class({
|
||||||
|
Extends: mindplot.nlayout.SymetricSorder
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
mindplot.nlayout.GridSorter.GRID_HORIZONTAR_SIZE = 50;
|
||||||
|
mindplot.nlayout.GridSorter.INTER_NODE_VERTICAL_DISTANCE = 50;
|
||||||
|
|
115
mindplot/src/main/javascript/nlayout/LayoutManager.js
Normal file
115
mindplot/src/main/javascript/nlayout/LayoutManager.js
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
mindplot.nlayout.LayoutManager = new Class({
|
||||||
|
Extends: Events,
|
||||||
|
initialize: function(rootNodeId, rootSize) {
|
||||||
|
$assert($defined(rootNodeId), "rootNodeId can not be null");
|
||||||
|
$assert(rootSize, "rootSize can not be null");
|
||||||
|
|
||||||
|
this._treeSet = new mindplot.nlayout.RootedTreeSet();
|
||||||
|
this._layout = new mindplot.nlayout.OriginalLayout(this._treeSet);
|
||||||
|
|
||||||
|
var rootNode = this._layout.createNode(rootNodeId, rootSize, {x:0,y:0}, 'root');
|
||||||
|
this._treeSet.setRoot(rootNode);
|
||||||
|
this._events = [];
|
||||||
|
},
|
||||||
|
|
||||||
|
updateNodeSize: function(id, size) {
|
||||||
|
var node = this._treeSet.find(id);
|
||||||
|
node.setSize(size);
|
||||||
|
},
|
||||||
|
|
||||||
|
updateShirkState: function(id, isShrink) {
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
connectNode: function(parentId, childId, order) {
|
||||||
|
$assert($defined(parentId), "parentId can not be null");
|
||||||
|
$assert($defined(childId), "childId can not be null");
|
||||||
|
$assert($defined(order), "order can not be null");
|
||||||
|
|
||||||
|
this._layout.connectNode(parentId, childId, order);
|
||||||
|
},
|
||||||
|
|
||||||
|
disconnectNode: function(sourceId) {
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
deleteNode : function(id) {
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
addNode:function(id, size, position) {
|
||||||
|
$assert($defined(id), "id can not be null");
|
||||||
|
var result = this._layout.createNode(id, size, position, 'topic');
|
||||||
|
this._treeSet.add(result);
|
||||||
|
},
|
||||||
|
|
||||||
|
predict: function(parentId, childId, position) {
|
||||||
|
$assert($defined(parentId), "parentId can not be null");
|
||||||
|
$assert($defined(childId), "childId can not be null");
|
||||||
|
$assert(position, "childId can not be null");
|
||||||
|
|
||||||
|
var parent = this._treeSet.find(parentId);
|
||||||
|
var sorter = parent.getSorter();
|
||||||
|
var result = sorter.predict(parent, this._treeSet, position);
|
||||||
|
},
|
||||||
|
|
||||||
|
dump: function() {
|
||||||
|
console.log(this._treeSet.dump());
|
||||||
|
},
|
||||||
|
|
||||||
|
layout: function(fireEvents) {
|
||||||
|
// File repositioning ...
|
||||||
|
this._layout.layout();
|
||||||
|
|
||||||
|
// Collect changes ...
|
||||||
|
this._collectChanges();
|
||||||
|
|
||||||
|
if (fireEvents) {
|
||||||
|
this.flushEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
flushEvents: function() {
|
||||||
|
this._events.forEach(function(event) {
|
||||||
|
this.fireEvent('change', event);
|
||||||
|
}, this);
|
||||||
|
this._events = [];
|
||||||
|
},
|
||||||
|
|
||||||
|
_collectChanges: function(nodes) {
|
||||||
|
if (!nodes)
|
||||||
|
nodes = this._treeSet.getTreeRoots();
|
||||||
|
|
||||||
|
nodes.forEach(function(node) {
|
||||||
|
if (node.hasOrderChanged() || node.hasPositionChanged()) {
|
||||||
|
|
||||||
|
// Find or create a event ...
|
||||||
|
var id = node.getId();
|
||||||
|
var event = this._events.some(function(event) {
|
||||||
|
return event.id == id;
|
||||||
|
});
|
||||||
|
if (!event) {
|
||||||
|
event = new mindplot.nlayout.ChangeEvent(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update nodes ...
|
||||||
|
if (node.hasOrderChanged()) {
|
||||||
|
event.setOrder(node.getOrder());
|
||||||
|
node.resetOrderState();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.hasPositionChanged()) {
|
||||||
|
event.setPosition(node.getPosition());
|
||||||
|
node.resetPositionState();
|
||||||
|
}
|
||||||
|
this._events.push(event);
|
||||||
|
}
|
||||||
|
this._collectChanges(this._treeSet.getChildren(node));
|
||||||
|
}, this);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
117
mindplot/src/main/javascript/nlayout/Node.js
Normal file
117
mindplot/src/main/javascript/nlayout/Node.js
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
mindplot.nlayout.Node = new Class({
|
||||||
|
initialize:function(id, size, position, sorter) {
|
||||||
|
$assert(!isNaN(id), "id can not be null");
|
||||||
|
$assert(size, "size can not be null");
|
||||||
|
$assert(position, "position can not be null");
|
||||||
|
$assert(sorter, "sorter can not be null");
|
||||||
|
|
||||||
|
this._id = id;
|
||||||
|
this._sorter = sorter;
|
||||||
|
this._properties = {};
|
||||||
|
|
||||||
|
this.setSize(size);
|
||||||
|
this.setPosition(position);
|
||||||
|
},
|
||||||
|
|
||||||
|
getId:function() {
|
||||||
|
return this._id;
|
||||||
|
},
|
||||||
|
|
||||||
|
setOrder: function(order) {
|
||||||
|
$assert(!isNaN(order), "Order can not be null");
|
||||||
|
this._setProperty('order', order, false);
|
||||||
|
},
|
||||||
|
|
||||||
|
resetPositionState : function() {
|
||||||
|
var prop = this._properties['position'];
|
||||||
|
if (prop) {
|
||||||
|
prop.hasChanded = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
resetOrderState : function() {
|
||||||
|
var prop = this._properties['order'];
|
||||||
|
if (prop) {
|
||||||
|
prop.hasChanded = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
getOrder: function() {
|
||||||
|
return this._getProperty('order');
|
||||||
|
},
|
||||||
|
|
||||||
|
hasOrderChanged: function() {
|
||||||
|
return this._isPropertyChanged('order');
|
||||||
|
},
|
||||||
|
|
||||||
|
hasPositionChanged: function() {
|
||||||
|
return this._isPropertyChanged('position');
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
getPosition: function() {
|
||||||
|
return this._getProperty('position');
|
||||||
|
},
|
||||||
|
|
||||||
|
setSize : function(size) {
|
||||||
|
$assert($defined(size), "Size can not be null");
|
||||||
|
this._setProperty('size', Object.clone(size));
|
||||||
|
},
|
||||||
|
|
||||||
|
getSize: function() {
|
||||||
|
return this._getProperty('size');
|
||||||
|
},
|
||||||
|
|
||||||
|
setPosition : function(position) {
|
||||||
|
$assert($defined(position), "Position can not be null");
|
||||||
|
$assert(!isNaN(position.x), "x can not be null");
|
||||||
|
$assert(!isNaN(position.y), "y can not be null");
|
||||||
|
|
||||||
|
this._setProperty('position', Object.clone(position));
|
||||||
|
},
|
||||||
|
|
||||||
|
_setProperty: function(key, value) {
|
||||||
|
var prop = this._properties[key];
|
||||||
|
if (!prop) {
|
||||||
|
prop = {
|
||||||
|
hasChanded:false,
|
||||||
|
value: null,
|
||||||
|
oldValue : null
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
prop.oldValue = prop.value;
|
||||||
|
prop.value = value;
|
||||||
|
prop.hasChanded = true;
|
||||||
|
|
||||||
|
this._properties[key] = prop;
|
||||||
|
},
|
||||||
|
|
||||||
|
_getProperty: function(key) {
|
||||||
|
var prop = this._properties[key];
|
||||||
|
return $defined(prop) ? prop.value : null;
|
||||||
|
},
|
||||||
|
|
||||||
|
_isPropertyChanged: function(key) {
|
||||||
|
var prop = this._properties[key];
|
||||||
|
return prop ? prop.hasChanded : false;
|
||||||
|
},
|
||||||
|
|
||||||
|
_setPropertyUpdated : function(key) {
|
||||||
|
var prop = this._properties[key];
|
||||||
|
if (prop) {
|
||||||
|
this._properties[key] = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
getSorter: function() {
|
||||||
|
return this._sorter;
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
toString: function() {
|
||||||
|
return "[order:" + this.getOrder() + ", position: {" + this.getPosition().x + "," + this.getPosition().y + "}]";
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
90
mindplot/src/main/javascript/nlayout/OriginalLayout.js
Normal file
90
mindplot/src/main/javascript/nlayout/OriginalLayout.js
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
mindplot.nlayout.OriginalLayout = new Class({
|
||||||
|
initialize: function(treeSet) {
|
||||||
|
this._treeSet = treeSet;
|
||||||
|
|
||||||
|
this._heightByNode = {};
|
||||||
|
},
|
||||||
|
|
||||||
|
createNode:function(id, size, position, type) {
|
||||||
|
$assert($defined(id), "id can not be null");
|
||||||
|
$assert(size, "size can not be null");
|
||||||
|
$assert(position, "position can not be null");
|
||||||
|
$assert(type, "type can not be null");
|
||||||
|
|
||||||
|
var strategy = type === 'root' ? mindplot.nlayout.OriginalLayout.GRID_SORTER : mindplot.nlayout.OriginalLayout.SYMETRIC_SORTER;
|
||||||
|
return new mindplot.nlayout.Node(id, size, position, strategy);
|
||||||
|
},
|
||||||
|
|
||||||
|
connectNode: function(parentId, childId, order) {
|
||||||
|
|
||||||
|
var parent = this._treeSet.find(parentId);
|
||||||
|
var child = this._treeSet.find(childId);
|
||||||
|
|
||||||
|
// Connect the new node ...
|
||||||
|
this._treeSet.connect(parentId, childId);
|
||||||
|
|
||||||
|
// Insert the new node ...
|
||||||
|
var sorter = parent.getSorter();
|
||||||
|
sorter.insert(this._treeSet, parent, child, order);
|
||||||
|
|
||||||
|
// Fire a basic validation ...
|
||||||
|
sorter.verify(this._treeSet, parent);
|
||||||
|
},
|
||||||
|
|
||||||
|
layout: function() {
|
||||||
|
var roots = this._treeSet.getTreeRoots();
|
||||||
|
roots.forEach(function(node) {
|
||||||
|
|
||||||
|
// Calculate all node heights ...
|
||||||
|
var sorter = node.getSorter();
|
||||||
|
|
||||||
|
// @Todo: This must not be implemented in this way.Each sorter could have different notion of heights ...
|
||||||
|
var heightById = sorter.computeChildrenIdByHeights(this._treeSet, node);
|
||||||
|
|
||||||
|
this._layoutChildren(node, heightById);
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
|
// Finally, return the list of nodes and properties that has been changed during the layout ...
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
_layoutChildren: function(node, heightById) {
|
||||||
|
|
||||||
|
var nodeId = node.getId();
|
||||||
|
var children = this._treeSet.getChildren(node);
|
||||||
|
var childrenOrderMoved = children.some(function(child) {
|
||||||
|
return child.hasOrderChanged();
|
||||||
|
});
|
||||||
|
var heightChanged = this._heightByNode[nodeId] != heightById[nodeId];
|
||||||
|
throw "Esto no esta bien:"+ this._heightByNode;
|
||||||
|
|
||||||
|
// If ether any of the nodes has been changed of position or the height of the children is not
|
||||||
|
// the same, children nodes must be repositioned ....
|
||||||
|
if (childrenOrderMoved || heightChanged) {
|
||||||
|
|
||||||
|
var sorter = node.getSorter();
|
||||||
|
var offsetById = sorter.computeOffsets(this._treeSet, node);
|
||||||
|
var parentPosition = node.getPosition();
|
||||||
|
|
||||||
|
children.forEach(function(child) {
|
||||||
|
var offset = offsetById[child.getId()];
|
||||||
|
var newPos = {x:parentPosition.x + offset.x,y:parentPosition.y + offset.y};
|
||||||
|
this._treeSet.updateBranchPosition(child, newPos);
|
||||||
|
}.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Continue reordering the children nodes ...
|
||||||
|
children.forEach(function(child) {
|
||||||
|
this._layoutChildren(child, heightById);
|
||||||
|
}.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
mindplot.nlayout.OriginalLayout.SYMETRIC_SORTER = new mindplot.nlayout.SymetricSorder();
|
||||||
|
mindplot.nlayout.OriginalLayout.GRID_SORTER = new mindplot.nlayout.SymetricSorder();
|
||||||
|
|
||||||
|
|
||||||
|
|
141
mindplot/src/main/javascript/nlayout/RootedTreeSet.js
Normal file
141
mindplot/src/main/javascript/nlayout/RootedTreeSet.js
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
mindplot.nlayout.RootedTreeSet = new Class({
|
||||||
|
initialize:function() {
|
||||||
|
this._rootNodes = [];
|
||||||
|
},
|
||||||
|
|
||||||
|
setRoot:function(root) {
|
||||||
|
$assert(root, 'root can not be null');
|
||||||
|
this._rootNodes.push(this._decodate(root));
|
||||||
|
},
|
||||||
|
|
||||||
|
getTreeRoots:function() {
|
||||||
|
return this._rootNodes;
|
||||||
|
},
|
||||||
|
|
||||||
|
_decodate:function(node) {
|
||||||
|
node._children = [];
|
||||||
|
return node;
|
||||||
|
},
|
||||||
|
|
||||||
|
add: function(node) {
|
||||||
|
$assert(node, 'node can not be null');
|
||||||
|
$assert(!node._children, 'node already added');
|
||||||
|
this._rootNodes.push(this._decodate(node));
|
||||||
|
},
|
||||||
|
|
||||||
|
remove: function(node) {
|
||||||
|
throw "Must be implemted";
|
||||||
|
},
|
||||||
|
|
||||||
|
connect: function(parentId, childId) {
|
||||||
|
$assert($defined(parentId), 'parent can not be null');
|
||||||
|
$assert($defined(childId), 'child can not be null');
|
||||||
|
|
||||||
|
var parent = this.find(parentId, true);
|
||||||
|
var child = this.find(childId, true);
|
||||||
|
$assert(!child._parent, 'node already connected. Id:' + child.getId() + ",previous:" + child._parent);
|
||||||
|
|
||||||
|
|
||||||
|
parent._children.push(child);
|
||||||
|
child._parent = parent;
|
||||||
|
this._rootNodes.erase(child);
|
||||||
|
},
|
||||||
|
|
||||||
|
disconnect: function(nodeId) {
|
||||||
|
$assert(node, 'node can not be null');
|
||||||
|
$assert(node._parent, 'child node not connected connected');
|
||||||
|
|
||||||
|
node._parent._children.erase(node);
|
||||||
|
this._isolated.push(node);
|
||||||
|
|
||||||
|
node._parent = null;
|
||||||
|
},
|
||||||
|
|
||||||
|
find:function(id, validate) {
|
||||||
|
$assert($defined(id), 'id can not be null');
|
||||||
|
|
||||||
|
var graphs = this._rootNodes;
|
||||||
|
var result = null;
|
||||||
|
for (var i = 0; i < graphs.length; i++) {
|
||||||
|
var node = graphs[i];
|
||||||
|
result = this._find(id, node);
|
||||||
|
if (result) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$assert(validate ? result : true, 'node could not be found id:' + id);
|
||||||
|
return result;
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
_find:function(id, parent) {
|
||||||
|
if (parent.getId() == id) {
|
||||||
|
return parent;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = null;
|
||||||
|
var children = parent._children;
|
||||||
|
for (var i = 0; i < children.length; i++) {
|
||||||
|
var child = children[i];
|
||||||
|
result = this._find(id, child);
|
||||||
|
if (result)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
|
||||||
|
getChildren:function(node) {
|
||||||
|
$assert(node, 'node can not be null');
|
||||||
|
return node._children;
|
||||||
|
},
|
||||||
|
|
||||||
|
dump: function() {
|
||||||
|
var branches = this._rootNodes;
|
||||||
|
var result = "";
|
||||||
|
for (var i = 0; i < branches.length; i++) {
|
||||||
|
var branch = branches[i];
|
||||||
|
result += this._dump(branch, "");
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
|
||||||
|
_dump:function(node, indent) {
|
||||||
|
var result = indent + node + "\n";
|
||||||
|
var children = this.getChildren(node);
|
||||||
|
for (var i = 0; i < children.length; i++) {
|
||||||
|
var child = children[i];
|
||||||
|
result += this._dump(child, indent + " ");
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
|
||||||
|
updateBranchPosition : function(node, position) {
|
||||||
|
|
||||||
|
var oldPos = node.getPosition();
|
||||||
|
node.setPosition(position);
|
||||||
|
|
||||||
|
var xOffset = oldPos.x - position.x;
|
||||||
|
var yOffset = oldPos.y - position.y;
|
||||||
|
|
||||||
|
var children = this.getChildren(node);
|
||||||
|
children.forEach(function(child) {
|
||||||
|
this._shiftBranchPosition(child, xOffset, yOffset);
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
_shiftBranchPosition : function(node, xOffset, yOffset) {
|
||||||
|
var position = node.getPosition();
|
||||||
|
node.setPosition({x:position.x + xOffset, y:position.y + yOffset});
|
||||||
|
|
||||||
|
var children = this.getChildren(node);
|
||||||
|
children.forEach(function(child) {
|
||||||
|
this._shiftBranchPosition(child, xOffset, yOffset);
|
||||||
|
}.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
139
mindplot/src/main/javascript/nlayout/SymetricSorter.js
Normal file
139
mindplot/src/main/javascript/nlayout/SymetricSorter.js
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
mindplot.nlayout.SymetricSorder = new Class({
|
||||||
|
Extends: mindplot.nlayout.ChildrenSorterStrategy,
|
||||||
|
initialize:function() {
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
computeChildrenIdByHeights: function(treeSet, node) {
|
||||||
|
var result = {};
|
||||||
|
this._computeChildrenHeight(treeSet, node, result);
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
_computeChildrenHeight : function(treeSet, node, heightCache) {
|
||||||
|
var height = node.getSize().height + (mindplot.nlayout.SymetricSorder.INTERNODE_VERTICAL_PADDING * 2); // 2* Top and down padding;
|
||||||
|
|
||||||
|
var result;
|
||||||
|
var children = treeSet.getChildren(node);
|
||||||
|
if (children.length == 0) {
|
||||||
|
result = height;
|
||||||
|
} else {
|
||||||
|
var childrenHeight = 0;
|
||||||
|
children.forEach(function(child) {
|
||||||
|
childrenHeight += this._computeChildrenHeight(treeSet, child, heightCache);
|
||||||
|
}, this);
|
||||||
|
|
||||||
|
result = Math.max(height, childrenHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (heightCache) {
|
||||||
|
heightCache[node.getId()] = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
|
||||||
|
predict : function(parent, graph, position) {
|
||||||
|
|
||||||
|
// No children...
|
||||||
|
var children = graph.getChildren(parent);
|
||||||
|
if (children.length == 0) {
|
||||||
|
return [0,parent.getPosition()];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to fit within ...
|
||||||
|
//
|
||||||
|
// - Order is change if the position top position is changed ...
|
||||||
|
// - Suggested position is the middle bitween the two topics...
|
||||||
|
//
|
||||||
|
var result = null;
|
||||||
|
children.forEach(function(child) {
|
||||||
|
var cpos = child.getPosition();
|
||||||
|
if (position.y > cpos.y) {
|
||||||
|
result = [child.getOrder(),{x:cpos.x,y:cpos.y + child.getSize().height}];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Ok, no overlap. Suggest a new order.
|
||||||
|
if (result) {
|
||||||
|
var last = children.getLast();
|
||||||
|
result = [last.getOrder() + 1,{x:cpos.x,y:cpos.y - (mindplot.nlayout.SymetricSorder.INTERNODE_VERTICAL_PADDING * 4)}];
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
|
||||||
|
insert: function(treeSet, parent, child, order) {
|
||||||
|
var children = treeSet.getChildren(parent);
|
||||||
|
$assert(order <= children.length, "Order must be continues and can not have holes. Order:" + order);
|
||||||
|
|
||||||
|
// Sort array list ..
|
||||||
|
children.sort(function(a, b) {
|
||||||
|
return a.getOrder() - b.getOrder()
|
||||||
|
});
|
||||||
|
|
||||||
|
// Shift all the elements in one .
|
||||||
|
for (var i = order; i < children.length; i++) {
|
||||||
|
var node = children[i];
|
||||||
|
node.setOrder(node.getOrder() + 1);
|
||||||
|
}
|
||||||
|
child.setOrder(order);
|
||||||
|
},
|
||||||
|
|
||||||
|
verify:function(treeSet, node) {
|
||||||
|
// Check that all is consistent ...
|
||||||
|
var children = treeSet.getChildren(node);
|
||||||
|
children.sort(function(a, b) {
|
||||||
|
return a.getOrder() - b.getOrder()
|
||||||
|
});
|
||||||
|
|
||||||
|
for (var i = 0; i < children.length; i++) {
|
||||||
|
$assert(children[i].getOrder() == i, "missing order elements");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
computeOffsets:function(treeSet, node) {
|
||||||
|
$assert(treeSet, "treeSet can no be null.");
|
||||||
|
$assert(node, "node can no be null.");
|
||||||
|
$assert("order can no be null.");
|
||||||
|
|
||||||
|
var children = treeSet.getChildren(node);
|
||||||
|
children.sort(function(a, b) {
|
||||||
|
return a.getOrder() - b.getOrder()
|
||||||
|
});
|
||||||
|
|
||||||
|
// Compute heights ...
|
||||||
|
var heights = children.map(function(child) {
|
||||||
|
return {id:child.getId(),height:this._computeChildrenHeight(treeSet, child)};
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
|
// Compute the center of the branch ...
|
||||||
|
var totalHeight = 0;
|
||||||
|
heights.forEach(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 yOffset = ysum + mindplot.nlayout.SymetricSorder.INTERNODE_VERTICAL_PADDING;
|
||||||
|
var xOffset = mindplot.nlayout.SymetricSorder.INTERNODE_HORIZONTAL_PADDING;
|
||||||
|
|
||||||
|
$assert(!isNaN(xOffset), "xOffset can not be null");
|
||||||
|
$assert(!isNaN(yOffset), "yOffset can not be null");
|
||||||
|
|
||||||
|
result[heights[i].id] = {x:xOffset,y:yOffset};
|
||||||
|
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
mindplot.nlayout.SymetricSorder.INTERNODE_VERTICAL_PADDING = 5;
|
||||||
|
mindplot.nlayout.SymetricSorder.INTERNODE_HORIZONTAL_PADDING = 5;
|
||||||
|
|
||||||
|
|
70
mindplot/src/main/javascript/nlayout/TestSuite.js
Normal file
70
mindplot/src/main/javascript/nlayout/TestSuite.js
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
mindplot.nlayout.TestSuite = new Class({
|
||||||
|
Extends: mindplot.nlayout.ChildrenSorterStrategy,
|
||||||
|
initialize:function() {
|
||||||
|
|
||||||
|
// this.testAligned();
|
||||||
|
this.testEvents();
|
||||||
|
|
||||||
|
// @ Agregar tests que garantice que no se reposicional cosan inecesariamente 2 veces...
|
||||||
|
},
|
||||||
|
|
||||||
|
testAligned: function() {
|
||||||
|
|
||||||
|
var size = {width:30,height:30};
|
||||||
|
var position = {x:0,y:0};
|
||||||
|
var manager = new mindplot.nlayout.LayoutManager(0, size);
|
||||||
|
|
||||||
|
manager.addNode(1, size, position);
|
||||||
|
manager.connectNode(0, 1, 0);
|
||||||
|
|
||||||
|
manager.layout();
|
||||||
|
manager.dump();
|
||||||
|
},
|
||||||
|
|
||||||
|
testEvents: function() {
|
||||||
|
var size = {width:10,height:10};
|
||||||
|
var position = {x:0,y:0};
|
||||||
|
var manager = new mindplot.nlayout.LayoutManager(0, size);
|
||||||
|
|
||||||
|
// Add 3 nodes...
|
||||||
|
manager.addNode(1, size, position);
|
||||||
|
manager.addNode(2, size, position);
|
||||||
|
manager.addNode(3, size, position);
|
||||||
|
manager.addNode(4, size, position);
|
||||||
|
|
||||||
|
// Now connect one with two....
|
||||||
|
manager.connectNode(0, 1, 0);
|
||||||
|
manager.connectNode(0, 2, 0);
|
||||||
|
manager.connectNode(1, 3, 0);
|
||||||
|
|
||||||
|
// Reposition ...
|
||||||
|
manager.layout();
|
||||||
|
console.log("Updated tree:");
|
||||||
|
manager.dump();
|
||||||
|
|
||||||
|
// Listen for changes ...
|
||||||
|
console.log("Updated nodes ...");
|
||||||
|
var events = [];
|
||||||
|
manager.addEvent('change', function(event) {
|
||||||
|
console.log("Updated nodes: {id:" + event.getId() + ", order: " + event.getOrder() + ",position: {" + event.getPosition().x + "," + event.getPosition().y + "}");
|
||||||
|
events.push(event);
|
||||||
|
});
|
||||||
|
manager.flushEvents();
|
||||||
|
|
||||||
|
// Second flush must not fire events ...
|
||||||
|
console.log("---- Test Flush ---");
|
||||||
|
|
||||||
|
events.empty();
|
||||||
|
manager.flushEvents();
|
||||||
|
$assert(events.length == 0, "Event should not be fire twice.");
|
||||||
|
|
||||||
|
// Ok, if a new node is added, this an event should be fired ...
|
||||||
|
console.log("---- Layout without changes should not affect the tree ---");
|
||||||
|
events.empty();
|
||||||
|
manager.layout(true);
|
||||||
|
|
||||||
|
$assert(events.length == 0, "Unnecessary tree updated.");
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
41
mindplot/src/test/javascript/static/layout.html
Normal file
41
mindplot/src/test/javascript/static/layout.html
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<script type='text/javascript'
|
||||||
|
src='../../../../../wise-doc/src/main/webapp/js/mootools-core-1.3.2-full-compat.js'></script>
|
||||||
|
<script type='text/javascript'
|
||||||
|
src='../../../../../wise-doc/src/main/webapp/js/mootools-more-1.3.2.1-yui.js'></script>
|
||||||
|
|
||||||
|
|
||||||
|
<script type='text/javascript' src='../../../main/javascript/header.js'></script>
|
||||||
|
<script type='text/javascript' src='../../../../../core-js/target/classes/core.js'></script>
|
||||||
|
|
||||||
|
<script type='text/javascript' src='../../../main/javascript/widget/ToolbarItem.js'></script>
|
||||||
|
<script type='text/javascript' src='../../../main/javascript/widget/ColorPalettePanel.js'></script>
|
||||||
|
|
||||||
|
<script type='text/javascript'>
|
||||||
|
window.addEvent("load", function(e) {
|
||||||
|
var model = {
|
||||||
|
getValue: function() {
|
||||||
|
|
||||||
|
},
|
||||||
|
setValue : function(value) {
|
||||||
|
console.log("value:" + value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var palette = new mindplot.widget.ColorPalettePanel('myButton', model,"/mindplot/src/main/javascript/widget");
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div id="myButton" style="border: 1px red solid">
|
||||||
|
The button
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Reference in New Issue
Block a user