ActionScript 3.0, Adobe Flex

Flex : URI Class implementation

Browsing through the my company’s code repository (what else to do Saturday night ?) I found a number of different URI class implementations… whereas they did differ a little bit in implementation, the overall implementations were very similar and mostly differed in quality.

None of them however were as good as Mike Chambers’ implementation which can be found in the AS3CoreLib.

If you have not yet checked it out yet and you sometimes find yourself in need of a good URI class implementation, consider using this one…

http://code.google.com/p/as3corelib/source/browse/trunk/src/com/adobe/net/URI.as

ActionScript 3.0, Adobe Flex

Flex : Pageable ArrayCollection with support for active paging

Yesterday one of the developers in my company had the need for a PagedArrayCollection. A quick search on Google revealed only this implementation, which turned out to be buggy so I decided to implement one myself.

I designed an interface called IPagedCollection which in combination with an extension of the existing mx.collections.ArrayCollection implementation would do the job.

Only hurdle was the need to override addItemAt and removeItemAt as the autoUpdate doesn’t seem to work when a filterFunction is employed. I will look in to this phenomena, but as for now a call to refresh after inserting or removing does the job nicely.

The code itself is quite simple, I have also created a small demo-application which illustrates the use of the collection.

Live Demo

Download of Sources

/**
 * Copyright(c) 2008 HelloGroup A/S, some rights reserved.
 * Your reuse is governed by the Creative Commons Attribution 3.0 Denmark License
**/
package com.hello.collections
{
	public interface IPagedArrayCollection
	{
		function get currentPage() : Number
		function set currentPage( value:Number ) : void;

		function get numberOfPages() : Number;

		function get pageSize() : Number;
		function set pageSize( value:Number ) : void;

		function get lengthTotal() : Number;
	}
}
/**
 * Copyright(c) 2008 HelloGroup A/S, some rights reserved.
 * Your reuse is governed by the Creative Commons Attribution 3.0 Denmark License
 *
 * Known Issues:
 * - When the collection changes in size or pagesize, the currentPage is not updated. This is a problem if currentPage is set to a higher value than in the new collection.
**/
package com.hello.collections
{
	import mx.collections.ArrayCollection;
	import mx.events.CollectionEvent;

	public class PagedArrayCollection extends ArrayCollection implements IPagedArrayCollection
	{
		private var _currentPage:Number = 1;
		private var _numberOfPages:Number = 1;
		private var _pageSize:Number = 10;

		public function PagedArrayCollection(source:Array=null)
		{
			super( source );
			filterFunction = filterData;
			addEventListener( CollectionEvent.COLLECTION_CHANGE, onChange );
		}

		/**
		 * Adds an item to the collection at the specified index.
		 *
		 * @param item Item to be added
		 * @param index Index of the item to be added
		 *
		 * Note: Needs to be overridden in order to trigger refresh. AddItem eventually calls this function so its not needed to override addItem
		 */
		override public function addItemAt( item:Object, index:int ) : void
		{
			super.addItemAt( item, index );
			refresh();
		}

		/**
		 * Removes the item from the collection at the specified index
		 *
		 * @param index Index of the item to be removed
		 * @return The item removed
		 *
		 * Note: Needs to be overridden in order to trigger refresh
		 */
		override public function removeItemAt( index:int ) : Object
		{
			var removedItem:Object = super.removeItemAt( index );
			refresh();
			return removedItem;
		}

		protected function onChange( event:CollectionEvent ) : void
		{
			if( _numberOfPages != numberOfPages )
			{
				_numberOfPages = numberOfPages;
				onPagingChange( PagedCollectionEventKind.NUMBEROFPAGES_CHANGE );
			}
		}

		protected function onPagingChange( kind:String ) : void
		{
			dispatchEvent( new CollectionEvent( CollectionEvent.COLLECTION_CHANGE, false, false, kind ) );
		}

		[ChangeEvent("collectionChange")]
		public function get currentPage() : Number
		{
			return _currentPage;
		}
		public function set currentPage( value:Number ) : void
		{
			_currentPage = value;
			refresh();
			onPagingChange( PagedCollectionEventKind.CURRENTPAGE_CHANGE );
		}

		[ChangeEvent("collectionChange")]
		public function get numberOfPages() : Number
		{
			var result:Number = source.length / pageSize;
			result = Math.ceil( result );
			return result;
		}

		[ChangeEvent("collectionChange")]
		public function get pageSize() : Number
		{
			return _pageSize;
		}
		public function set pageSize( value:Number ) : void
		{
			_pageSize = value;
			refresh();
			onPagingChange( PagedCollectionEventKind.PAGESIZE_CHANGE );
		}

		[ChangeEvent("collectionChange")]
		public function get lengthTotal() : Number
		{
			return source.length;
		}

		private function filterData( item:Object ) : Boolean
		{
			var dataWindowCeiling:Number = pageSize * currentPage;
			var dataWindowFloor:Number = dataWindowCeiling - pageSize;

			var itemIndex:Number = getItemIndex( item );

			var result:Boolean = dataWindowFloor <= itemIndex && itemIndex < dataWindowCeiling;
			return result;
		}
	}
}

/**
* Copyright(c) 2008 HelloGroup A/S, some rights reserved.
* Your reuse is governed by the Creative Commons Attribution 3.0 Denmark License
**/
package com.hello.collections
{
public class PagedCollectionEventKind
{
public static const CURRENTPAGE_CHANGE:String = "currentPageChange";
public static const PAGESIZE_CHANGE:String = "pageSizeChange";
public static const NUMBEROFPAGES_CHANGE:String = "numberOfPagesChange";
}
}

Adobe Flex

Flex SDK : Skinning in Flex 4 (Codename: Gumbo)

The Flash Player is the delivery mechanism for some of the most creative work to be found on the web today. Flex applications however have gained a reputation for looking too similar to each other, as many developers choose to use the Flex default look and feel (known as Halo) as opposed to applying extensive styling or skinning. Research performed by Adobe shows that only 46% of our frequent Flex users do extensive skinning while only 22% even do major style adjustments. This is not to say that customization never happens, but Adobe found that it remains too challenging to create a truly custom experience. It is therefore a priority for Gumbo (The new version of the Flex SDK) to make easy customization of Flex application experiences the norm instead of the exception.

Exciting stuff… Check it out…
http://opensource.adobe.com/wiki/display/flexsdk/Gumbo+Themes

Adobe Flex

Google Trends of XAML and MXML

Despite the huge momentum Adobe Flex have gained the last year or so, its clear that XAML still have more momentum overall, according to Google Trends.

XAML is the markup language from Microsoft to create RIA’s and one of the cornerstones in Silverlight, MS’s “new” primary RIA platform. MXML is the markup language used in Adobe Flex, Adobe’s primary RIA platform and has been around for quite a shorter time than XAML.

Here is a direct link to the comparison I did:
http://www.google.com/trends?q=xaml%2Cmxml



An interesting observation is related to the geographical distribution of the searches, seeing that India is top-ranking in regards to Country, however in regards to City its Redmond, VA (The home of Microsoft).

Another interesting point is that Denmark and Danish is at the time of this comparison (it’s off course subject to change, partly due to the dynamics of the Google indexing system based on statistically enhanced numbers and off course due to the fact that the numbers eventually do change over the course of time) ranked 10 and 6 respectively, positioning the Danish RIA community high on the international rank.
Combine this with the positions of our brothering countries, Sweden and Norway, Scandinavia is definitely in the super-liga of RIA regions.

Adobe Flex

Adobe Flex : The Undocumented StaticEventDispatcher

There is an undocumented feature of the Flex Compiler which can come in quite handy.

If you have wanted to listen for changes to static variables, there is an undocumented static variable called “staticEventDispatcher” on classes that have one or more static variables prior to compilation.
The way it works is that as part of compiler pre-processing, the Flex compiler adds a static EventDispatcher object to the class, which eventually can be used to listen for PropertyChangeEvents on the class-reference itself.

If the class does not have a static variable at compiler preprocessing time, the staticEventDispatcher is not added. Despite the i-logic of the fact that a public static property (getter/setter functions) does NOT result in the pre-processor adding the staticEventDispatcher reference it can off course be worked around by adding a variable which references the function in which you have not broken the “contract” of the class, but still have “triggered” the Flex compiler to add your staticEventDispatcher.

The code below is just exploratory-code, and should off course NOT be used anywhere, it just proves the point about the discrepancy about static properties and variables.

public static var getSomethingFunction : Function = something as Function;
public static function get something() : String { return "Hello World"; }

This feature of the Flex compiler is very closely related to an undocumented class in the Flex framework, its the StaticPropertyWatcher which extends its more wellknown cousin, the Watcher class in the same mx.binding.* namespace.
Seeing that the StaticPropertyWatcher actually uses the staticEventDispatcher mechanism of the Flex compiler, and seeing that the ordinary Watcher class uses the StaticPropertyWatcher there is no reason not to use this feature.

However, an important point is that in order to ensure forward-compatibility I recommend that you use the staticEventDispatcher in a more type-strict fashion then the StaticPropertyWatcher implementation.

The following excerpt is taken from the StaticPropertyWatcher, and as you can see – they reference it through the class-index and not directly. By doing this you don’t allow the compiler to capture classes attempting to use the static EventDispatcher reference without having a static variable resulting in runtime errors in situations where you don’t check for it’s existance prior to use.

        parentObj = Class(parent);

if (parentObj["staticEventDispatcher"] != null)
{
for (var eventType:String in events)
{
if (eventType != "__NoChangeEvent__")
{
var eventDispatcher:IEventDispatcher = parentObj["staticEventDispatcher"];

eventDispatcher.addEventListener(eventType, eventHandler, false,
EventPriority.BINDING, true);
}
}
}

In the above case its not possible to do a more type-strict notation seeing that its generic framework code, however in cases where the code is more business-logic-oriented the following notation would make a bit more sense for the compiler

parentObj.staticEventDispatcher.addEventListener( PropertyChangeEvent.PROPERTY_CHANGE, onSomeobjectChange );

This is the preferred way and also a pretty cool way to listen for changes to static variables, despite the fact that its not documented.