In this final step we will place every node in it's correct position, from the previous step we know that the width of the entire control depends on the number of nodes without children and the number of level, so, we can easily place the nodes without children, its position is given by the up left corner position (x, y).
For every node without children we have:
x = (n - 1) * nodeWidth + (n - 1) * hSpace + hSpace; // n = number of node without children y = (l - 1) * nodeHeight + (l - 1) * vSpace + vSpace; // l = number of level
the previous formulas can be writen like this:
x = (n - 1) * (nodeWidth + hSpace) + hSpace; // n = number of node without children y = (l - 1) * (nodeHeight + vSpace) + vSpace; // l = number of level
After placing nodes without children it is very easy to place parent nodes, we just have to recognize that a parent node its at a lower level and in the middle of its first and last children.
To analyze nodes of the entire tree, we will call a recursive function and pass an array reference to let u count how many nodes without children we find.
We have to do this on the updateDisplayList function, let's see how to implemented it.
// Implement updateDisplayList function
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void{
super.updateDisplayList(unscaledWidth,unscaledHeight);
if(rootNode){
// We will calculate the order in wich the nodes should be placed.
var nodesWOC:Array = [0];
var posRoot:Array = placeNode(rootNode,1, nodesWOC);
drawPathLines(rootNode);
}
else{
graphics.clear();
}
}
The placeNode function will place all the modes begining with the nodes without children.
private function placeNode(node:Node, level:uint, nodesWOC:Array):Array{
var nodeHeight:Number = node.height;
var nodeWidth:Number = node.width;
if(!node.childNodes){
// Placing a node without children
nodesWOC[0] = (nodesWOC[0] as Number ) + 1;
node.move( ( nodeWidth + _hSpace )* ( (nodesWOC[0] as Number) - 1) + _hSpace, (nodeHeight + _vSpace) * (level - 1) + _vSpace );
return [ (nodeWidth + _hSpace )* ( (nodesWOC[0] as Number) - 1) + _hSpace, (nodeHeight + _vSpace) * (level - 1) + _vSpace];
}
else{
// Placing a parent node
var positionX:Number;
var positionY:Number;
var posFirst:Array;
var posLast:Array;
var posTemp:Array;
// Placing all children first
for( var iNode:Number = 0; iNode < node.childNodes.length; iNode++ ){
var childNode:Node = node.childNodes[iNode];
posTemp = placeNode(childNode, level + 1, nodesWOC);
if( iNode == 0){
posFirst = posTemp;
}
if( iNode == node.childNodes.length - 1){
posLast = posTemp;
}
}
// Calculating position for parent node based on first and last children
positionX = ( (posFirst[0] as Number) + (posLast[0] as Number) )/2;
positionY = (nodeHeight + _vSpace) * (level - 1) + _vSpace;
node.move(positionX, positionY);
return [positionX, positionY];
}
}
Well, that's all the "difficult" part, I'm sure you can handle what is not explained here.
I hope you liked it.