Building Blocks It is not enough for code to work. Code that works is often badly broken

25Mar/080

Renju – AS3 board game built with the PureMVC framework.

renju.jpg

This is awesome. Here is a polished board game with nice graphics and sounds - full AI - and best of all, the complete source. This is a great example of PureMVC in action. All of the projects on Actionscript Notes utilize PureMVC, and the owner seems to be generous with the source. Many thanks for that.

23Mar/080

Christian Cantrell's ever-growing selection of useful Actionscript 3/AIR libraries.

Here's the full list of what he has on Google Code.

The CoreLib is essential, but he's been busy writing useful libraries for AIR. I've used the notification library, which has some great features and makes notifications on the desktop sensible. The exchange library is interesting, for sure. They are all worth checking out.

There are also a number of interesting example applications using AIR, including a motion detection application, an Amazon S3 interface, a screen saver, and an MS Exchange calendar.

23Mar/082

I had an epiphany as to what polymorphism is last night.

Yes, I know I am late to the party. I can't even estimate how many times I've read a definition of an Interface over the last year. It has been a concept that totally baffled me for a long time, then I sorta understood, and last night I actually implemented an Interface intentionally and correctly. The same is true for the term polymorphism. I can read definitions until my eyes hurt, but until I actually use it, the words are just abstractions. These two concepts are synonymous, as Interfaces in Actionscript 3 are a convenience for type-checking polymorphism in APIs.

'Ah-ha!'

In this case, I had a Flex container that I wanted to pass to a method. I didn't know what the container would be, but I knew that it would be a container. IContainer? Yup. Now the method couldn't care less what class is being passed its way, as long as it has the appropriate methods that match the IContainer signature.

Now it makes sense. This is the reason I keep reading that I need to use implicit getters and setters with private class properties instead of public properties. Public properties are not allowed in an interface, so you aren't able to abstract these properties with an interface. Getters and setters ARE allowed in an interface, so now you can expose these properties and ensure that methods expecting the interface get what they are looking for. As it turns out, people weren't recommending this simply to get me to write extra lines of code ;)

The pieces are starting to come together. Abstract classes, design patterns, polymorphism, interfaces... PureMVC has been a help. The framework pushes me towards proper OOP and the use of design patterns. Stacking knowledge, one block at a time.

21Mar/084

Flex component transformation with ObjectHandles

Rogue Development's ObjectHandles is a great component. It is simple to use and provides all of the functionality that I was looking for in a transformation modifier. Prior to implementing this, I was using the TransformTool from senocular.com's library. This is also a great utility, but it wants to scale my content, and that was a deal breaker in my current project. ObjectHandles does NOT resize the child components. There are use cases for both approaches, but ObjectHandles allows me to decide when to scale.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?xml version="1.0" encoding="utf-8"?>
<objectHandles
	xmlns="com.roguedevelopment.objecthandles.*"
	xmlns:mx="http://www.adobe.com/2006/mxml"
	allowRotate="false"
	objectMovedEvent="objectUpdatedHandler( event )"
	width="{image.width}"
	height="{image.height}" >
<mx:Script>
	<![CDATA[
		import com.roguedevelopment.objecthandles.ObjectHandlesMouseCursors;
		public static const CHANGE:String = "imageBoxChanged";
 
		private function objectUpdatedHandler( event:Event ):void
		{
			dispatchEvent( new Event( CHANGE, true ) );
		}
	]]>
</mx:Script>
	<mx:Image id="image" source="@Embed(source='/assets/cower.png')" />
</objectHandles>
Filed under: components, flex 4 Comments
20Mar/081

Animated collision of two crane trucks.

I spend a lot of my time animating horrific accidents.  It's a great way to make a living - once you get past the original reference pictures. The above is from a case that recently cleared. Watch your speakers, it has audio.

18Mar/082

Accessing a List from its itemRenderer

This was really throwing me off tonight. I could not figure out how to get at the List from its itemRenderer. this.parent... no this.owner... no

So I started The Search™, trying to hunt down The Answer™. This is one of those things that doesn't just jump out of the manual at you. Luckily, Peter Ent is running an extremely informative series on itemRenders. He says to get at the List, we need to simply access the listData property. But there's a catch:

Most controls such as Text, Label, Button, CheckBox, and so forth, implement IDropInListItemRenderer. Most containers, such as HBox, Canvas, etc. do not implement that interface. If you want to use listData in an itemRenderer that extends a Container you will have to implement IDropInListItemRenderer yourself - I'll cover that in the next article.

Luckily for us, it is a simple process:

1
<mx:hbox xmlns:mx="http://www.adobe.com/2006/mxml" implements="mx.controls.listClasses.IDropInListItemRenderer"></mx:hbox>

We will need to implement the appropriate methods in the itemRenderer's Script tag also:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import mx.controls.listClasses.BaseListData;
 
private var _listData:BaseListData;
private var list:List;
 
public function get listData() : BaseListData
{
	return _listData;
}
public function set listData( value:BaseListData ) : void
{
	_listData = value;
	list = listData.owner as List
	list.addEventListener( ListEvent.CHANGE, onListChange, false, 0, true )
}

In my case, I wanted to listen for changes so that I could set one of the itemRenderer sub-component's properties whenever the list had changed. Now to access the List:

if ( list.selectedItem == data ) doSomeStuff();

Easy as that.

Filed under: actionscript, flex 2 Comments
18Mar/080

PureMVC Python port has been released

[PureMVC - Python]

I am very excited about the potential of this port. As far as I can tell, there isn't a whole lot out there for MVC and Python. There are a handful of server/web MVC frameworks. Django is the one that I have experience with, and it is a fantastic framework. As is true when comparing PureMVC to most frameworks, however, the PureMVC for Python is dead simple. It is a straight port, implementing PureMVC in the same fashion as we see in the original AS3 version. Structurally it differs from Actionscript - it is Python after all - but fundamentally it is the same.

Many thanks to Toby de Havilland for overcoming some of the initial issues with the port, and getting it up and running. Thanks also to Nathan Levesque for running point on the project and getting the ball rolling with the port

Here it is running the Employee Admin demo on XP and OSX:

pmvc_python.jpg pmvc_py_mac.jpg.

Filed under: puremvc, python No Comments
15Mar/088

5 reasons PureMVC kicks ass

PureMVC is a lightweight MVC framework originally written for Actionscript 3, but which has subsequently been ported to a host of other platforms. I'm a PureMVC fan boy. There is no denying it. Here are few reasons why:

Simplicity
There are a few MVC frameworks available for Actionscript 3. None of them are, well... as pure. PureMVC is simple by design. It doesn't provide you with a lot of bells and whistles. What it does is provide a solid foundation upon which to add your own functionality in limitless ways. The framework itself is simple. 'Make it as simple as possible, but no simpler,' said Albert Einstein. This is one of the core goals of PureMVC.

Community
The PureMVC community is growing. The Architect's Lounge has high signal to noise ratio. Cliff makes a super human effort to personally answer every question that is posted. Among the helpful community members is Chandima Cumaranatunge, the co-author of a book that anybody interested in OO Actionscript should own, Actionscript 3 Design Patterns.

Cliff has created the PureMVC Manifold Project, which provides a well crafted central location for official PureMVC releases, and a host of ports, demos, and utilities developed by the community. This wealth of information provides a high quality code base to use and learn from.

Reusability
As you can see by poking around the Manifold Project, there are a lot of utilities and modules already available. The basic structure of a PureMVC project naturally lends itself to the creation of common classes that can be reused across many projects. Major components don't care who is sitting beside them. They happily wait for their notifications and respond without considering their neighbors. In some circles this would be considered rude, but in a PureMVC application this gives a wonderful, loosely couple application that can be refactored and recycled.

Portability
The port to Python is done!  PureMVC is on Flex, Flash, AIR, FlashLite, Python, .NET, Windows Mobile, Silverlight, J2ME, SE, EE, JavaFX, PHP and ColdFusion. This speaks to the simplicity of the framework. It is so fundamental, that most of the ports were just straight translation.

Cliff
Cliff is samurai. He is the benevolent, tireless dictator that any flowering project needs. He is actively engaged with the community. On a daily basis he is on the forums answering questions. The structuring of the ever-expanding pile of resources and information into something useful is daunting task. There it is with the Manifold Project. It is inspiring to see someone so passionate about what they do, and channeling that passion back at anyone interested in learning.

Thanks Cliff, your efforts are greatly appreciated.

14Mar/082

Complex DataGrid filterFunction in Flex/Air

So I need to add robust user controlled filtering options in the application I am working on. This problem has dogged me for a month or two, with my co-workers politely insisting on more and better ways to filter their data. This is completely understandable. When you are staring down a datagrid that is virtually 12 feet long, getting to what you actually want to see is important.

This 2006 article from Bruce Phillips was a big help in the basic concept of multiple input filtering. As is his normal style, it is littered with good references to the source material from his research. This is only considering two filter parameters, however, and I need to consider n parameters, that will probably shift as the needs of the end user grow.

The problem is that each new filtering parameter exponentially increases the complexity of the filterFunction. I can see the pattern, but I haven't quite reached the epiphany that I need to break it down into one of those tight little functions I see real programmers creating (unfortunately, I haven't seen any that address my specific problem).

I thought I'd share my naive, and perhaps confusing filterFunction. It would be great to hear how others approach this problem, and come up with a concise solution.

This function utilizes a TextInput to get text search input from the user. It uses
a series of CheckBoxes for various status condition to generate an array [ 1, 0, 1, 1 ]
to represent their on/off state. It also uses two combo boxes to filter by staff members
as well as clients.

filterFunction:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
private function filterCases(item:CaseVO):Boolean
{
	//is the item visible or hidden
	var result:Boolean = false;
	//array of CheckBox.selected property values
       // in handy ones and zeroes. This is returned from a function
       // that takes the actual CheckBoxes as input and gives me this.
	var case_mask:Array = [ 1, 0, 1, 1 ];
        //a couple VOs to verify the selectedItem in the ComboBoxes.
	var client:PersonVO;
	var expert:PersonVO;
	//array iteration variable
	var i:int;
 
	var dateFormat:DateFormatter = new DateFormatter( )
	dateFormat.formatString = 'MM/DD/YY'
 
	//text search
	if ( caseGrid.filter.caseNumInput.text.length &gt; 0 )
	{
		var searchResult:Boolean = ( ( String( '0' + item.case_id.toString() ).search( caseGrid.filter.caseNumInput.text ) &gt;= 0 ) ||
										( item.style.toLowerCase().search( caseGrid.filter.caseNumInput.text.toLowerCase() ) &gt;= 0 )  );
		if( item.description )
		{
			searchResult = searchResult || ( item.description.toLowerCase().search( caseGrid.filter.caseNumInput.text.toLowerCase() ) &gt;= 0 )
		}
 
		if ( item.client_id )
		{
			searchResult = searchResult || ( personProxy.personFromId( item.client_id ).fullName.toLowerCase().search( caseGrid.filter.caseNumInput.text.toLowerCase() ) &gt;= 0 )
		}
 
		if ( item.date_of_accident )
		{
			searchResult = searchResult || ( dateFormat.format(item.date_of_accident).search( caseGrid.filter.caseNumInput.text ) &gt;= 0 )
		}
 
		for ( i = 0; i &lt; case_mask.length; i++ )
		{
			if ( caseGrid.filter.client.selectedItem is PersonVO )
			{
				client = caseGrid.filter.client.selectedItem
 
				//is an expert selected for filtering also?
				if ( caseGrid.filter.expert.selectedItem is PersonVO &amp;&amp; searchResult)
				{
					expert = caseGrid.filter.expert.selectedItem;
					//filter for client, expert, and status
					if ( (case_mask[i] &amp;&amp; item.status == String( i + 1 ) )
							&amp;&amp; item.client_id == client.id
							&amp;&amp; item.expert_id == expert.id &amp;&amp; searchResult  )
						result = true;
				}
				else
				{
					//filter for client and status
					if ( (case_mask[i] &amp;&amp; item.status == String( i + 1 ) )
							&amp;&amp; item.client_id == client.id &amp;&amp; searchResult  )
						result = true;
				}
			}
			else if ( caseGrid.filter.expert.selectedItem is PersonVO )
			{
				expert = caseGrid.filter.expert.selectedItem;
				for ( i = 0; i &lt; case_mask.length; i++ )
				{
					//filter for expert and status
					 if ( (case_mask[i] &amp;&amp; item.status == String( i + 1 ) )
					 		&amp;&amp; item.expert_id == expert.id &amp;&amp; searchResult  )
					 	result = true
				}
 
			}
			else
			{
				//filter for client and status
				if ( (case_mask[i] &amp;&amp; item.status == String( i + 1 ) )
						&amp;&amp; searchResult  )
					result = true;
			}
		}
	}
	//see if a client is selected for filtering
	else if ( caseGrid.filter.client.selectedItem is PersonVO )
	{
		client = caseGrid.filter.client.selectedItem
		for ( i = 0; i &lt; case_mask.length; i++ )
		{
			//is an expert selected for filtering also?
			if ( caseGrid.filter.expert.selectedItem is PersonVO )
			{
				expert = caseGrid.filter.expert.selectedItem;
				//filter for client, expert, and status
				if ( (case_mask[i] &amp;&amp; item.status == String( i + 1 ) )
						&amp;&amp; item.client_id == client.id
						&amp;&amp; item.expert_id == expert.id  )
					result = true;
			}
			else
			{
				//filter for client and status
				if ( (case_mask[i] &amp;&amp; item.status == String( i + 1 ) )
						&amp;&amp; item.client_id == client.id  )
					result = true;
			}
		}
	}
	//client isn't selected, check the expert filter.
	else if ( caseGrid.filter.expert.selectedItem is PersonVO )
	{
		expert = caseGrid.filter.expert.selectedItem;
		for ( i = 0; i &lt; case_mask.length; i++ )
		{
			//filter for expert and status
			 if ( (case_mask[i] &amp;&amp; item.status == String( i + 1 ) )
			 		&amp;&amp; item.expert_id == expert.id  )
			 	result = true
		}
 
	}
	//finally, filter for the status
	else
	{
		for ( i = 0; i &lt; case_mask.length; i++ )
		{
			//filter for status
			if ( case_mask[i] &amp;&amp; item.status == String( i + 1 ) )
				result = true;
		}
	}
 
	return result
}

You can see that I am repeating myself from the top down to the final else statement, cutting the filter parameters down like a layer cake. It works, and is relatively quick on a grid with 1500 or so items. This just screams "REFACTOR ME" every time I see it.

Filed under: AIR, OCD, actionscript, flex 2 Comments