Step 3: Implementing the Node class

Before reading this step, you have to download the source code of this control from the FlexTuts Library section, that way it will be easier to understand what we are doing.

Calculating the size (width and height) of a node
The following image will help us calculate the total width and height

from the image we can say:

nodeWidth = border + picture.width + space + title.width + border
nodeHeight = border + max ( picture.height , title.height + description.height ) + border

Overriding functions in the Node class
When you make a visual control you must at least inherit from the UIComponent of the mx.core package, in this case we made it inherit from Canvas just to avoid some events implementation like the "click".

There are some function you must override for your control to work properly and they are:

createChildren : will be called by the system when the control is created
commitProperties : will be called by the system when invalidateProperties is called
measure : will be called by the system when needs to calculate you control's size
updateDisplayList : will be called by the system when its time to place all controls insite yours.

In the createChildren function we create the objects that will be used in our Node control.

private var thumbnail:Image;
private var title:Text;
private var description:Text;

// Implement createChildren function. 
override protected function createChildren():void {
	super.createChildren();
	if(!thumbnail) { // validate if the thumbnail object was created before
		thumbnail = new Image(); // creates an image object
		thumbnail.explicitHeight = 60; // asigning a default value
		thumbnail.explicitWidth = 54; // asigning a default value
		thumbnail.setStyle("borderStyle", "solid");
		addChild(thumbnail);
	}
	if(!title) { // validate if the title object was created before
		title = new Text(); // creates a text object
		title.explicitWidth = 100;  // asigning a default value
		title.explicitHeight = 20;  // asigning a default value
		title.selectable = false; 
		title.setStyle("color",0xFFFFFF);
		title.setStyle("fontWeight","bold");
		addChild(title);
	}
	if(!description){ // validate if the description object was created before
		description = new Text(); // creates a text object
		description.explicitWidth = 100; // asigning a default value
		description.explicitHeight = 40; // asigning a default value
		description.selectable = false;
		description.setStyle("fontWeight","bold");
		addChild(description);
	}
	this.addEventListener("click", handleEventClick);
}

In the commitProperties function we assign values from the temporary variables to the controls created before

// Implement commitProperties function.
override protected function commitProperties():void{
	super.commitProperties();
	if(_thumbnailChanged){
		_thumbnailChanged = false;
		thumbnail.source = _thumbSource;
	}
	if(_descriptionChanged){
		_descriptionChanged = false;
		description.text = _descText;
	}
	if(_titleChanged){
		_titleChanged = false;
		title.text = _titleText;
	}	
}

In the measure function we calculate the control size, here we will use the formula we got from the image a the top.

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

	var titleWidth:Number;
	var descWidth:Number;
	var thumbWidth:Number = thumbnail.getExplicitOrMeasuredWidth();
	
	titleWidth = descWidth = Math.max( title.getExplicitOrMeasuredWidth(), description.getExplicitOrMeasuredWidth());
	title.measuredWidth = titleWidth;
	description.measuredWidth = descWidth;
	
	var titleHeight:Number = title.getExplicitOrMeasuredHeight();
	var descHeight:Number = description.getExplicitOrMeasuredHeight();
	var thumbHeight:Number = thumbnail.getExplicitOrMeasuredHeight();
	
	this.measuredWidth = this.measuredMinWidth = border + thumbWidth + space + titleWidth + border;
	this.measuredHeight = this.measuredMinHeight = Math.max(titleHeight + descHeight, thumbHeight) + 2 * border;
}

In the updateDisplayList function we place the controls in the position they should go.

override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void{
	super.updateDisplayList(unscaledWidth, unscaledHeight);
		
	var titleWidth:Number;
	var descWidth:Number;
	var thumbWidth:Number = thumbnail.getExplicitOrMeasuredWidth();
	
	titleWidth = descWidth = Math.max( title.getExplicitOrMeasuredWidth(), description.getExplicitOrMeasuredWidth());

	var titleHeight:Number = title.getExplicitOrMeasuredHeight();
	var descHeight:Number = description.getExplicitOrMeasuredHeight();
	var thumbHeight:Number = thumbnail.getExplicitOrMeasuredHeight();

	// Set actual size of each child component
	// Set thumbnail actual size
	thumbnail.setActualSize(thumbWidth, thumbHeight);
	// Set title actual size
	title.setActualSize(titleWidth, titleHeight);
	// Set description actual size
	description.setActualSize(descWidth, descHeight);
		
	// Placing thumbnail 
	thumbnail.move(border, border);
		
	// Placing title
	title.move(border + thumbWidth + space, border);
		
	//  Placing description
	description.move(border + thumbWidth + space, border + titleHeight);  
}