Step 5: Implementing the Organigram Class

The Node class was simple, the Organigram is not going to be different, as we did before we need to implement a constructor, override some functions and implement some additional functions.

Calculating the size (width and height) of the organigram
Let's check the picture

To calculate the width we have to find all the nodes without children in the picture those nodes are numbered from 1 to 9, in general we will use N as the number of nodes without children, so we have the next formula for the minimun width:

organigram.width = hSpace + N * node.width + ( N - 1 ) * hSpace + hSpace

Calculating the height is easier, in the image we see 5 levels, we will use L to denote the number of level:

organigram.height = vSpace + L * node.height + ( L - 1 ) * vSpace + vSpace

Implementing the contructor

// Implement the constructor
public function Organigram(){
	super();
}

Overriding functions in the Organigram class

In this case the createChildren will not do anything special, just call the commitProperties super class method. We will create the children controls later.

// Implement createChildren function
override protected function createChildren():void{
	super.createChildren();
}

The same occurs with the commitProperties function

// Implement commitProperties function.
override protected function commitProperties():void{
	super.commitProperties();
}

In the measure function we need to calculate the size of our control, for this we will create two additional functions that will give us the number of levels (countLevels) and the number of nodes without children (countNodesWithoutChilden).

// Implement measure function.
override protected function measure():void{
	super.measure();
	
	if(rootNode){
		// Use new functions to calculate with and height
		 var nLevels:uint = countLevels(rootNode);
		 var nFinalNodes:uint = countNodesWithoutChildren(rootNode);
				 
		 // Calculate with ( we assume that all nodes have the same with )
		 var nodeWidth:Number = rootNode.width;
		 var compWidth:Number = nFinalNodes * nodeWidth + (nFinalNodes + 1) * _hSpace ;
				 
		 // Calculate height
		 var nodeHeight:Number = rootNode.height;
		 var compHeight:Number = nLevels * nodeHeight + (nLevels + 1 ) * _vSpace ;
				 
		 this.measuredWidth = this.measuredMinWidth = compWidth;
		 this.measuredHeight = this.measuredMinHeight = compHeight;
	}
}

The countLevel function looks for the highest level of all the children for a given node.

// Calculates how many level have this tree
private function countLevels(node:Node, level:uint = 1):uint{
	if(node)
	{
		if(!node.childNodes){
			return level;
		}
		else{
			var maxLevel:uint = level;
			for( var iNode:Number = 0; iNode < node.childNodes.length ; iNode++) {
				var childNode:Node = node.childNodes[iNode] as Node;
				maxLevel = Math.max(maxLevel, countLevels(childNode, level + 1));
			}
			return maxLevel;
		}
	}
	else{
		return 0;
	}
}

The countNodesWithoutChildren is also recursive and returns 1 for any node withoutchildren, if the node has children it evaluates every children and accumulates the returned values.

// Calculates how many nodes without children have this tree  
private function countNodesWithoutChildren(node:Node):uint{
	if(node){
		if(!node.childNodes){
			return 1;
		}
		else{
			var count:uint = 0;
			for( var iNode:Number = 0; iNode < node.childNodes.length ; iNode++){
				var childNode:Node = node.childNodes[iNode] as Node;
				count += countNodesWithoutChildren(childNode);
			}
			return count;
		}
	}
	else{
		return 0;
	}
}

In the next step we will see how to place every node in the correct position.