Cursor/Iterator for Vector and Array

10.24.2010

Along with Flex came IViewCursor which provides a way to itererate through ICollectionView classes like ArrayCollection and XMLListCollection. Sometimes though we’re dealing with Vector or Array or are developing an ActionScript-only project. Here’s a cursor/iterator that will allow you to navigate a Vector or Array:

package com.aaronhardy
{
	import flash.utils.Proxy;
	import flash.utils.flash_proxy;
 
	use namespace flash_proxy;
 
	/**
	 * Allows for maintaining an index and iterating through a vector or array of objects.
	 */
	public class VectorCursor extends Proxy
	{
		/**
		 * The collection the cursor is navigating.
		 */
		protected var collection:*;
 
		/**
		 * The current cursor index.
		 */
		protected var index:int;
 
		public function VectorCursor(collection:*)
		{
			this.collection = collection;
		}
 
		/**
		 * The item at the current cursor index.
		 */
		public function get current():Object
		{
			return index > -1 && index < collection.length ? collection[index] : null;
		}
 
		/**
		 * The current cursor index.
		 */
		public function get currentIndex():int
		{
			return index;
		}
 
		/**
		 * Moves the cursor index to the first item.
		 */
		public function seekFirst():void
		{
			index = 0;
		}
 
		/**
		 * Moves the cursor index to before the first item.
		 */
		public function seekBeforeFirst():void
		{
			index = -1;
		}
 
		/**
		 * Returns whether the cursor index is before the first item.
		 */
		public function get beforeFirst():Boolean
		{
			return index < 0;
		}
 
		/**
		 * Moves the cursor index to the last item.
		 */
		public function seekLast():void
		{
			index = collection.length - 1;
		}
 
		/**
		 * Moves the cursor index to after the last item.
		 */
		public function seekAfterLast():void
		{
			index = collection.length;
		}
 
		/**
		 * Returns whether the cursor index is after the last item.
		 */
		public function get afterLast():Boolean
		{
			return index >= collection.length;
		}
 
		/**
		 * Returns whether an item exists before the current cursor index.
		 */
		public function get hasPrevious():Boolean
		{
			return index > 0;
		}
 
		/**
		 * Moves the cursor index to and returns the previous item.
		 */
		public function movePrevious():Object
		{
			index--;
			return index > -1 ? collection[index] : null;
		}
 
		/**
		 * Returns whether an item exists after the current cursor index.
		 */
		public function get hasNext():Boolean
		{
			return index < collection.length - 1;
		}
 
		/**
		 * Moves the cursor index to and returns the next item.
		 */
		public function moveNext():Object
		{
			index++;
			return index < collection.length ? collection[index] : null;
		}
 
		// Overrides of proxy to provide for...each support.
 
		override flash_proxy function deleteProperty(name:*):Boolean {
			return false;
		}
 
		override flash_proxy function getProperty(name:*):* {
			return null;
		}
 
		override flash_proxy function hasProperty(name:*):Boolean {
			return true;
		}
 
		override flash_proxy function nextNameIndex(index:int):int {
			if (index > collection.length - 1)
				return 0;
			return index + 1;
		}
 
		override flash_proxy function nextName(index:int):String {
			return String(index - 1);
		}
 
		override flash_proxy function nextValue(index:int):* {
			return collection[index - 1];
		}
	}
}

And here are a few usage examples. Notice it supports for…each loops as well.

var vector:Vector.<User> = new Vector.<User>();
vector.push(new User('Bob'));
vector.push(new User('Jan'));
vector.push(new User('Sam'));
 
var cursor:VectorCursor = new VectorCursor(vector);
 
// Iterate from first to last.
while (!cursor.afterLast)
{
	trace(cursor.current);
	cursor.moveNext();
}
 
trace('----------');
 
// Iterate from last to first.
cursor.seekLast();
while (!cursor.beforeFirst)
{
	trace(cursor.current);
	cursor.movePrevious();
}
 
trace('----------');
 
// For...each example from first to last.
for each (var item:Object in cursor)
{
	trace(item);
}

Tags: , , , ,


Comments

10.25.2010 / Bryan Elkins said:

It’s about time. I was tempted to make one of these myself a while ago, but got sidetracked.

10.25.2010 / Sean Thayne said:

Would this allow you to use a Vector as a data provider for a display?

10.25.2010 / Aaron Hardy said:

If you mean as a data provider to spark data provider components, no. Sorry. You might want to check out Michael Labriola’s VectorCollection.


Leave a Comment

Your email address is required but will not be published.




Comment