05.19.08

Flex Item Renderers

Posted in Flex Code at 10:08 pm by rbezemer

So I’ll admit it, I’m still getting into the ActionScript programming frame of mind, and going from hardcore c++ to Flex takes a bit of a mind shift and I’m still getting used to flash doing everything for me, all though it is a nice change of pace.

An item renderer in flex is a relatively simple concept, basically for every item in a collection, here’s a set of components that can draw this data to some kind of human readable format that’s somewhat pleasing to the eye. Now the difficultly that I ran into was that I tried to get to smart for myself. I had a dataProvider that contained a tree of UIComponents that I wanted to manage in a list component, or more specifically a TileList. These components were generated by another in house library and I very much wanted to keep them in tack and not redraw everything out every time a change happened to the list (such as changing the number of columns from 4 to 8). Easy I thought, the behavior that makes the most sense is when the data provider is created it associates the item renderer with that index in the data provider so I did something like this in my item renderer:

override public function set data(value:Object):void
{
   _data = value as MyCustomContent
    //...
}
private function init():void{
    this.addChild(_data);
}

So what’s wrong with this…

Data item renderers were not meant to work this way. They very much rely on a UIComponent taking a temporary piece of data and having the component decide how to dynamically interprete this data. Many list componets are very “green” and recycle item renderers accross cell positions. While my above solution worked fine initially, when I started changing the number of columns all my data appeared in the wrong order. The List was shuffling item renderers between cells and when I associated content as a member variable in the renderer it was traveling to where ever the list decided to recycle an item renderer instead of having it travel with the index of the data provider. What makes me even madder at myself is if I had bothered to pay more attention to the documentation I’m sure I read that section about 20 times without realising what I was doing.

So moral of the story, always pay attention to what you are reading and make sure you properly update all your visual content each time an item renderer changes your data variable, don’t assume the same item renderer will use the same data each time it is rendered.

05.03.08

Create a Photobucket Image Gallery

Posted in Flex Code at 10:11 pm by rbezemer

Photobucket has a tonne of images that you can use to create some interesting content. I’m going to show you how to create a simple photobucket image gallery using Flex.

I love to reuse existing code where possible, probably one of my biggest sticky points as a software developer. In this case Doug Mccune has an awesome image dispaly component written using papervision and I’m just going to reuse his code. You can download his cover flow component here and link it into his code. I’m not going to go into a bunch of details on how to use his component, he has many links on his site on how to get it up and running.

After the coverflow component is linked in we’re going to create a light wrapper around it. Within your flex application go to new->Flex Component and create a component based on a Vbox.

The code looks something like this :

<mx:VBox createComplete="init()">
<containers:CoverFlowContainer
		id="coverflow"
		width="100%"
		height="100%"
		horizontalGap="40"
		borderStyle="solid"
		backgroundColor="0x000000"
		segments="10"
    	reflectionEnabled="true" />
	<mx:HScrollBar
		id="scrollbar"
		width="100%"
		pageSize="1"
        scrollPosition="{coverflow.selectedIndex}"
        scroll="coverflow.selectedIndex = Math.round(scrollbar.scrollPosition)" />
</mx:VBox>

Now the next thing we need is some script to dynamically add images to this component. Usually you can just add the objects you want to display in the coverflow component as child objects, but if we’re going to load them from Photobucket we need to be able to dynamically change them. Here is the code I use to dynamically add images:

	<!--[CDATA[
	public function addURL(url:String) : void {
		<!--
			Creates a canvas to display the image on
			and adds the canvas with the image as a
			Child of the coverflow component
		 -->
 		var cv:Canvas = new Canvas();
 		cv.width = canvasWidth;
 		cv.height = canvasHeight;
 		cv.verticalScrollPolicy="off";
 		cv.horizontalScrollPolicy="off";
 		var thisImage:Image = new Image();
 		thisImage.setStyle("verticalCenter","0");
		thisImage.setStyle("horizontalCenter","0");
		thisImage.addEventListener(Event.COMPLETE, imageLoaded);
		thisImage.load(url);
		cv.addChild(thisImage);
		coverflow.addChild(cv);
		numChildrenAdded++;
		scrollbar.setScrollProperties(1,0,numChildrenAdded-1,1);
		scrollbar.scrollPosition=coverflow.selectedIndex = Math.round(scrollbar.scrollPosition);
		coverflow.selectedIndex = numChildrenAdded-1;
	}			 	

	private function imageLoaded(event:Event):void{
		<!--
			Image Loader function to center the image
			after it has been loaded
		 -->
		var thisImage:Image = event.target as Image;
		if(thisImage.contentWidth>(canvasWidth-20) || thisImage.contentHeight>(canvasHeight-10)){
		var scaleAmt:Number = 1.0;
		if(pbImg.contentWidth>pbImg.contentHeight){
			scaleAmt = canvasWidth /(pbImg.contentWidth-10);
		}else{
			scaleAmt = canvasHeight /(pbImg.contentHeight-10);
		}
		pbImg.scaleX = scaleAmt;
		pbImg.scaleY = scaleAmt;
	 	}
	}
	]]–>

Now the next thing we need to do is to add the Photobucket content. For this example we are just going to display the 10 newest images on Photobucket using their RSS feeds. They have a API that allows you to really get detailed Photobucket information but that is a whole other article in itself. Any way the simplest way to do this is with a HTTPService Flex object:

<mx:HTTPService id="httpRSS"
		 url="http://feed.photobucket.com/recent/images/feed.rss"
		 resultFormat="object"
		 result="imagesAvailable(event)" />

Next you need to grab the image from the RSS XML:

 private function imagesAvailable(event:ResultEvent) : void {
	<!--
		This function simply pulls out the image guid from the
		RSS feed and sends the first 10 to the component
	-->
	for(var i:Number=0; i<10;i++){
		addURL(httpRSS.lastResult.rss.channel.item[i].guid);
	}
}

One final piece is to fill out the creationComplete function and tell it to load the rss feed at startup. Add the following to your components VBox tag:

creationComplete="{httpRSS.send()}"

And that is pretty much it! Hope this helped get you started creating a Photobucket image gallery.