This is a management class I like to use in enterprise applications to manipulate common data. It is usually a good design if using BlazeDS to turn on legacy collections so collections will be returned as an Array instead of an ArrayCollection. This will minimize processing and unless you are binding directly to the result, there is no reason to use an ArrayCollection that is dispatching events. These methods help in memory and performance management.

package com.justinimhoff.library.managers
{
 
    import flash.net.ObjectEncoding;
    import flash.net.registerClassAlias;
    import flash.utils.ByteArray;
    import flash.utils.describeType;
 
    import mx.collections.ArrayCollection;
    import mx.collections.ListCollectionView;
    import mx.collections.Sort;
    import mx.collections.SortField;
    import mx.utils.ObjectUtil;
 
    /**
     *
     *  The DataCollectionManager class is a utility class that allows for the management of
     *  Array, ArrayCollection, and Object. In cases where items need to be copied or cloned from multiple
     *  items, it is better to use this class because it impliments best practices for looping
     *  and event management.
     *
     * @see mx.collections.ArrayCollection
     *
     */
    public class DataCollectionManager extends Singleton
    {
 
        /**
         * Copies objects from one array to another and is left to the user to manage refresh or events if using source of ArrayCollection.
         *
         * @param sourceCollection The collection of all the inforamation that needs to be copied
         * @param targetCollection The collection to add to
         *
         */
        public function copyItemsToCollection(sourceCollection:Array, targetCollection:Array):void
        {
            var i:int = 0;
            var len:int = sourceCollection.length;
            for (; i < len; i++)
            {
                targetCollection.push(sourceCollection[i]);
            }
        }
 
        /**
         * Removes objects from a targeted collection. The items must be of the same object memory allocation
         *
         * @param itemsToRemove The Array of items to be removed
         * @param targetCollection The collection of where the items reside
         *
         */
        public function removeItemsFromCollection(itemsToRemove:Array, targetCollection:Array):void
        {
            var i:int = 0;
            var len:int = itemsToRemove.length;
            var itemIndex:int;
            for (; i < len; i++)
            {
                itemIndex = targetCollection.indexOf(itemsToRemove[i]);
                if (itemIndex < targetCollection.length + 1)
                {
                    targetCollection.splice(itemIndex, 1);
                }
            }
        }
 
 
        /**
         * Clones source of an ArrayCollection or Array into a target collection and manages the event lifecycle by dispatching one update.
         *
         * @param sourceCollection The collection of all the inforamation that needs to be copied
         * @param targetCollection The collection to add to
         *
         */
        public function cloneArrayToArrayCollection(sourceCollection:Array, targetCollection:ArrayCollection):void
        {
            targetCollection.disableAutoUpdate();
            targetCollection.removeAll();
            targetCollection.source = sourceCollection;
            targetCollection.enableAutoUpdate();
            targetCollection.refresh();
        }
 
        /**
         * Clones source of an ArrayCollection or Array into a target collection and cast the object by the provided type.
         * Also manages the event lifecycle by dispatching one update.
         *
         * @param sourceCollection The collection of all the inforamation that needs to be copied
         * @param targetCollection The collection to add to
         * @param classType The class to case each object as
         *
         */
        public function cloneArrayToArrayCollectionClassType(sourceCollection:Array, targetCollection:ArrayCollection, classType:Class):void
        {
            targetCollection.disableAutoUpdate();
            targetCollection.removeAll();
            var i:int = 0;
            var len:int = sourceCollection.length;
            for (; i < len; i++)
            {
                try
                {
                    targetCollection.addItem(sourceCollection[i] as classType);
                }
                catch (err:Error)
                {
                    trace('An error has occured in casting the object: ' + String(err.message));
                }
            }
            targetCollection.enableAutoUpdate();
            targetCollection.refresh();
        }
 
        /**
         * Converts a vector object to array for easy handling and also for instances where
         * switchng between mxml and spark components selected items.
         *
         * @param v The vector to copy into an Array
         * @return An array of items that where part of the vector
         *
         */
        public function convertVectorToArray(vector:Object):Array
        {
            var vec:Vector.<Object> = Vector.<Object>(vector);
            var arr:Array = [];
            for each (var i:Object in vec)
            {
                arr.push(i);
            }
            return arr;
        }
 
        /**
         * Recurively flatten nested objects and keep the property identifier and value of the property
         *
         * @param source The object that has information to copy
         * @param pushTo The clean object to push properties and value into
         *
         */
        public function pushToFlatObject(source:Object, pushTo:Object):void
        {
            var objectInfo:Object;
            var i:int;
            var len:int;
            for each (var item:* in source)
            {
                if (ObjectUtil.isSimple(item))
                {
                    objectInfo = ObjectUtil.getClassInfo(source);
                    i = 0;
                    len = objectInfo.properties.length;
                    for (; i < len; i++)
                    {
                        //Show the name and the value 
                        if (source[objectInfo.properties[i].localName] == item)
                        {
                            pushTo[objectInfo.properties[i].localName] = item;
                        }
                    }
                }
                else
                {
                    pushToFlatObject(item, pushTo);
                }
            }
        }
 
 
        /**
         * Converts a plain object to be an instance of the class
         * passed as the second variable.  This is not a recursive funtion
         * and will only work for the first level of nesting.  When you have
         * deeply nested objects, you first need to convert the nested
         * objects to class instances, and then convert the top level object.
         *
         * @param object The plain object that should be converted
         * @param clazz The type to convert the object to
         */
        public function objectToInstance(object:Object, clazz:Class):*
        {
            var bytes:ByteArray = new ByteArray();
            bytes.objectEncoding = ObjectEncoding.AMF0;
 
            // Write out the bytes of the original object
            var objBytes:ByteArray = new ByteArray();
            objBytes.objectEncoding = ObjectEncoding.AMF0;
            objBytes.writeObject(object);
 
            // Register all of the classes so they can be decoded via AMF
            var typeInfo:XML = describeType(clazz);
            var fullyQualifiedName:String = typeInfo.@name.toString().replace(/::/, ".");
            registerClassAlias(fullyQualifiedName, clazz);
 
            // Write the new object information starting with the class information
            var len:int = fullyQualifiedName.length;
            bytes.writeByte(0x10); // 0x10 is AMF0 for "typed object (class instance)"
            bytes.writeUTF(fullyQualifiedName);
            // After the class name is set up, write the rest of the object
            bytes.writeBytes(objBytes, 1);
 
            // Read in the object with the class property added and return that
            bytes.position = 0;
            var result:* = bytes.readObject();
            return result;
        }
 
        /**
         * Copies properties from one object to another
         *
         * @param copyTo The object to copy to
         * @param copyFrom The object to copy from = the source
         *
         */
        public function copyPropertiesToObject(copyTo:Object, copyFrom:Object):void
        {
            var objectInfo:Object = ObjectUtil.getClassInfo(copyFrom);
            var i:int = 0;
            var len:int = objectInfo.properties.length;
            for (; i < len; i++)
            {
                //Show the name and the value 
                if (copyTo.hasOwnProperty([ objectInfo.properties[i].localName ]))
                {
                    copyTo[objectInfo.properties[i].localName] = copyFrom[objectInfo.properties[i].localName];
                }
            }
        }
 
        /**
         * Allows the creation of multiple complex sorting for a provided collection. Provides the ability to customize the type of sort
         * and provides support for multiple sort fields.
         *
         * @param collection Supports Array and ListCollectionView.
         * @param sortItems An array of item identifiers to sort against, should be in an array of strings.
         * @param caseInsensitive When sorting strings, tells the comparitor whether to ignore the case of the values.
         * @param descending Tells the comparator whether to arrange items in descending order.
         * @param numeric Tells the comparitor whether to compare sort items as numbers, instead of alphabetically.
         *
         */		
        public function createSort(collection:*, sortItems:Array,caseInsensitive:Boolean=false,descending:Boolean=false,numeric:Object=null):void{
            var newSortField:SortField;
            var sortFieldList:Array = [];
            //Create sort fields
            for each(var sortItem:String in sortItems){
                newSortField = new SortField(sortItem,caseInsensitive,descending,numeric);
                sortFieldList.push(newSortField);
            }
            //Create sort and assign to correct dataprovider
            var collectionSort:Sort = new Sort();
            collectionSort.fields = sortFieldList;
            if(collection is Array){
                collection.sort = collectionSort;
            }else if(collection is ListCollectionView){
                collection.sort = collectionSort;
                collection.refresh();
            }
        }
    }
}

When using flex/flash and leveraging remote objects, there will be a time where you might need to dispatch two or more events simultaneous. The issue with this is when using BlazeDS you will run into a bundling effect of the events. The events will be fired in the same frame and as such they will be considered as a bundled request. The down side is that one request will affect the time of return for the other request.


Example:

Request 1 takes 135ms

Request 2 takes 784ms

These request will be processed as a bundle and will not be returned until both are performed so you will not benefit from performances tuned request and your result will be both returning in 919ms and your UI will have to process both pieces of information together instead of staggering layout.

The alternative is to make sure each event is dispatched in a separate frame so there is no bundling.

package com.justinimhoff.library.utilities
{
    import flash.events.EventDispatcher;
    import flash.events.TimerEvent;
    import flash.utils.Timer;
 
    /**
     *
     * Creates a queue of events that only one is dispatched every other key frame in order to
     * get away from bundling of events from the player an browser. When bundling of events occurs,
     * the slowest running will impac the result time of all others and items live on a single thread
     * server side.
     *
     */
    public class StaggeredRemoteDispatcher extends EventDispatcher
    {
        /**
         * set to low value so it will only dispatch on next keyframe
         * @private
         */
        private var dispatchTimer:Timer = new Timer(100);
 
        /**
         * a queue of events to dispatch
         * @private
         */
        private var events:Array = [];
 
        /**
         * Adds an event to the queue that will be called on the next frame event.
         * Starts the time and adds event listner for the next interval
         * @param event
         *
         */
        public function addFunction(item:Function):void
        {
            if (events.length == 0)
            {
                dispatchTimer.addEventListener(TimerEvent.TIMER, dispatchSequenceEvent);
                dispatchTimer.start();
            }
            events.push(item);
        }
 
        /**
         * Dispatches the next event in the queue and stops the timer and removes the event
         * listner if there are no more items.
         * @param event
         *
         */
        protected function dispatchSequenceEvent(event:TimerEvent):void
        {
            if (events.length > 0)
            {
                var callFunction:Function = events[0] as Function;
                callFunction.call();
		//remove just called function
		events.shift();
            }
			if(events.length == 0){
				dispatchTimer.stop();
				dispatchTimer.removeEventListener(TimerEvent.TIMER, dispatchSequenceEvent);
			}
        }
    }
}

I use this as the core Singleton management class in most enterprise applications. To use, make sure your new class extends Singleton and then in the view grab a instance of a Singleton management class. Extending the Singleton class allows leveraging event dispatching as if you extended the event dispatcher, but through the Singleton class you can manage the memory of Singletons by removing if not in use. This is a simple core class to use and leverage in your enterprise application.

 var viewManager:ViewManager = Singleton.getInstance(ViewManager);
package com.justinimhoff.library.managers
{
    public class ViewManager extends Singleton
    {
    }
}
 
package com.justinimhoff.library.managers
{
    import flash.events.Event;
    import flash.events.EventDispatcher;
    import flash.events.IEventDispatcher;
    import flash.utils.Dictionary;
    import flash.utils.getDefinitionByName;
    import flash.utils.getQualifiedClassName;
 
    /**
     *
     * General Singleton management class. Extend this class to create
     * a singleton manager.
     *
     */
    public class Singleton implements IEventDispatcher
    {
        /**
         * internal dictionary to keep class instances
         * @private
         */
        private static var instanceDict:Dictionary = new Dictionary();
 
        /**
         * removes the item from the dictionary for garbage collection
         * @param managementClass
         *
         */
        public static function removeInstance(managementClass:Class):void
        {
            var instance:Singleton = instanceDict[managementClass];
            if (instance != null)
            {
                delete instanceDict[managementClass];
            }
        }
 
        /**
         * Get the single instance
         * @return the single instance
         *
         */
        public static function getInstance(managementClass:Class):*
        {
            var instance:Singleton = instanceDict[managementClass];
            if (instance == null)
            {
                //create a new instance of class managementClass  
                instance = Singleton(new managementClass());
 
                if (instance == null)
                {
                    throw("getInstance can only be called for Classes extending Singleton");
                }
            }
            return instance;
        }
 
        /**
         * Dispatcher to user in singletons
         */
        protected var dispatcher:EventDispatcher = new EventDispatcher();
 
        /**
         *
         * We only want one of these - Singletons are actually more performant than static management classes
         *
         */
        public function Singleton()
        {
            onConstructor();
        }
 
        /**
         * Used to interface with internal dispatcher
         * @param type
         * @param listener
         * @param useCapture
         * @param priority
         * @param useWeakReference
         *
         */
        public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void
        {
            dispatcher.addEventListener(type, listener, useCapture, priority, useWeakReference);
        }
 
        /**
         * Used to interface with internal dispatcher
         * @param type
         * @param listener
         * @param useCapture
         *
         */
        public function removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void
        {
            dispatcher.removeEventListener(type, listener, useCapture);
        }
 
        /**
         * Used to interface with internal dispatcher
         * @param event
         * @return
         *
         */
        public function dispatchEvent(event:Event):Boolean
        {
            return dispatcher.dispatchEvent(event);
        }
 
        /**
         * Used to interface with internal dispatcher
         * @param type
         * @return
         *
         */
        public function hasEventListener(type:String):Boolean
        {
            return dispatcher.hasEventListener(type);
        }
 
        /**
         * Used to interface with internal dispatcher
         * @param type
         * @return
         *
         */
        public function willTrigger(type:String):Boolean
        {
            return dispatcher.willTrigger(type);
        }
 
        /**
         *
         * Conceptually private constructor.
         * Manages the singleton document dictionary.
         *
         */
        protected function onConstructor():void
        {
            var className:String = getQualifiedClassName(this);
            var managementClass:Class = getDefinitionByName(className) as Class;
            if (managementClass == Singleton)
            {
                throw("Singleton is a base class that cannot be instantiated");
            }
            var instance:Singleton = instanceDict[managementClass];
            if (instance != null)
            {
                throw("Classes extending Singleton can only be instantiated once by the getInstance method");
            }
            else
            {
                instanceDict[managementClass] = this;
            }
        }
        ;
    }
}

There are many cases where you will build a custom component library and use namespaces, this is what I have found to work the best. Can post step for creating and using a manifest, but there are many links on google. The key to this is using the current Adobe namespaces as not to overwrite and adding your own. When deploying the swc, make sure it is copied back into the libs directory so Flash builder can pick up the changes.


 
    <!-- build component library swc -->
    <macrodef name="flex-compile-production-swc">
        <attribute name="swc-name" />
        <attribute name="locale"
            default="en_US" />
        <sequential>
            <compc output="${source.libs}/library/@{swc-name}${version}.swc"
                locale="@{locale}"
                maxmemory="768m"
                fork="true"
                debug="false">
 
 
                <source-path path-element="${source.flex.dir}" />
                <include-sources dir="${source.flex.dir}/com/justinimhoff/library/"
                    includes="**/*.as **/*.mxml" />
 
                <namespace uri="http://ns.adobe.com/mxml/2009"
                    manifest="${FLEX_HOME}/frameworks/mxml-2009-manifest.xml" />
                <namespace uri="library://ns.adobe.com/flex/spark"
                    manifest="${FLEX_HOME}/frameworks/spark-manifest.xml" />
                <namespace uri="library://ns.adobe.com/flex/mx"
                    manifest="${FLEX_HOME}/frameworks/mx-manifest.xml" />
                <namespace uri="http://www.adobe.com/2006/mxml"
                    manifest="${FLEX_HOME}/frameworks/mxml-manifest.xml" />
 
                <namespace uri="library://justinimhoff.com/flex/components"
                    manifest="${source.libs.components}/component-manifest.xml" />
                <include-namespaces>library://justinimhoff.com/flex/components</include-namespaces>
 
                <!-- Externally linked Flex libraries -->
                <compiler.external-library-path dir="${FLEX_HOME}/frameworks/"
                    append="true">
                    <include name="libs/player/playerglobal.swc" />
                    <include name="libs/framework.swc" />
                    <include name="libs/spark.swc" />
                    <include name="libs/sparkskins.swc" />
                    <include name="libs/utilities.swc" />
                    <include name="libs/textLayout.swc" />
                    <include name="libs/rpc.swc" />
                    <include name="libs/flex.swc" />
                    <include name="locale/${locale}/framework_rb.swc" />
                    <include name="locale/${locale}/rpc_rb.swc" />
                </compiler.external-library-path>
            </compc>
            <copy preservelastmodified="true"
                todir="${output.dir.rsls}">
                <fileset casesensitive="yes"
                    dir="${source.libs}/library/">
                    <include name="@{swc-name}${version}.swc" />
                </fileset>
            </copy>
            <echo>Succesfully compiled @{swc-name}</echo>
        </sequential>
    </macrodef>

Quick demonstration of Kinect controlling Google Street View with Adobe AIR:




Controls:

  • Rotate body right: rotate image right
  • Rotate Body left: rotate image left
  • Walk (knee up): progress forward
  • Lean Up: look up
  • Lean Down: look down

This is a quick demonstration of leveraging the kinect for NUI with Street View. The example above uses AS3OpenNI (shout out) with Google Street View in Adobe AIR.

So  you are building a enterprise Flex application that uses automated builds with ant. You are running into the issue of multiple modules and assets that use the same name but you want to identify the swf by the specific version of the build and maybe even deploy multiple builds in the same structure allowing them to share un- changed resources. Or just maybe you want to make sure that when you deploy a new production build, that the swfs are not cached. The below code will help with both scenarios. As a quick background, when using RSLs, the RSL contains a digest or UID that when the application is compiled, it is compiled against that digest. When requesting RSLs, the application request RSLs by name but then also validates the digest against what the application was compiled against to ensure it is using the latest / correct library.

       /**
         * property in the build file that identifies the version number used to build swfs
         * @private
         */
        private static const BUILD_PROPERTY_VERSION_IDENTIFIER:String = 'version';
 
        /**
         * The regular expression that only allows numbers, dashes, and period from the build
         * property string
         * @private
         */
        private static const BUILD_PROPERTY_VERSION_REG_EXP:RegExp = /[^0-9-.]/g;
 
        [Embed(source="../build/build.properties", mimeType="application/octet-stream")]
        /**
         * Embedded build property file
         */
        private static const embeddedBuildFile:Class;
 
        /**
         * With searching if an item is not found it return -1, so anything 0 or greater means the
         * item has been found at least once in the string.
         */
        private static const ITEM_FOUND:int = 0;
 
        /**
         * The version of the application
         * @private
         */
        private var _appVersion:String = '';
 
        /**
         * If the property is not already set, loop through all build properties that have been embedded
         * when compiled until the property contains an identifier related to the build version. Once found,
         * clean up any characters that are not of a build number and set property
         * @return build version number
         *
         */
        public function get version():String
        {
            if (_appVersion == '')
            {
	        // Create a new class of the embedd type and cast as a string to initialize
		var buildProperties:String = String(new embeddedBuildFile());
		// Split all line breaks into an array
                var arr:Array = buildProperties.split("\n");
                var i:int = 0;
                var len:int = arr.length;
                var buildProperty:String;
	       // Loop through all poperties untile the identifier is found and set
                for (; i < len; i++)
                {
                    buildProperty = arr[i];
                    if (buildProperty.search(BUILD_PROPERTY_VERSION_IDENTIFIER) >= ITEM_FOUND)
                    {
                        _appVersion = buildProperty.replace(BUILD_PROPERTY_VERSION_REG_EXP, '');
                        break;
                    }
                }
            }
            return _appVersion;
        }

We want to essentially copy this same structure while also promote caching when possible. In most build scenarios you are versioning the application and maybe using automated incremental build numbers. This is a great thing and something we want to take advance of, so the first step is to embedded the build.properties file (properties.xml would require parsing as XML) so we have the incremented version or build number that the swf is being built as. When embedding the properties file, you can try decompiling the swf, but you will not be able to read out the file – only during runtime initialization will the values be available. This may be a great thing if you are using encryption keys in the application. So the file has the latest build so then the next step just comes to instantiating and looping through the values until the expected property is found and then just clean up the property values based on your versioning scheme.

The next step to this is to build out your applications, modules, and runtime assets with the build version appended. Example; Application.1.2.3-45678.swf or module.1.2.3-45678.swf. This allows a visual identifier of the build version and ability to deploy multiple applications of different builds to the same directory. Now the real reason we have embedded the version in the application is we need to know the URL for the assets or the modules – we know the identifier but need to append the version. This will allow an application to only load the correct module or asset swf for the specific build. This example can also be extended to custom libraries  or even as RSLs.

The other benefit to this approach is caching, when building Flex application we have all run into informing the client to clear there cache and try again – but no more. In this scenario the application.html page will be requesting a completely different swf file because it will be referencing the swf with the appended build, so it will always be fresh – but not just that, we also will be leveraging the caching of the swf in the browser. If the application.html file is pointing to the same swf consecutively it will use the cache of the swf and you will no worry about the client having the latest and greatest. You can use this in a singleton or static through-ought the application if there are other properties that might be worth noting like server build time . Can definitely go into more detail but hopefully this can help other out and is a good start.

This might seem like a small thing, but when you are requesting results back from the Google Maps API for example, and are presented with dynamic nested objects, your validation can be daunting. This simple function will allow you to pass in the object to be flattened into a blank object or an object you would like to append to. This will allow simple validation of the object, and the ability to convert to a strict type object if necessary. This was used in a singleton utility management class, if to be used in a static, add static and recursively call the class.

Simple = Yes / Time Saver = Hells Yes!

        public function pushToFlatObject(source:Object, pushTo:Object):void
        {
            for each (var item:* in source)
            {
                if (ObjectUtil.isSimple(item))
                {
                    var objectInfo:Object = ObjectUtil.getClassInfo(source);
                    var i:int = 0;
                    var len:int = objectInfo.properties.length;
                    for (; i &lt; len; i++)
                    {
                        //Show the name and the value
                        if (source[objectInfo.properties[i].localName] == item)
                        {
                            pushTo[objectInfo.properties[i].localName] = item;
                        }
                    }
                }
                else
                {
                    pushToFlatObject(item, pushTo);
                }
            }
        }

If you are using Flex 4 or even Flex 3 with the AdvancedDataGrid and you run into this error:

TypeError: Error #1007:Instantiation attempted on a non-constructor.at mx.controls::AdvancedDataGridBaseEx/getSeparator()

This is caused by the default css for the flex datavisualization library not including styles and class references that are required in the Advanced Data Grid.  You can either use the below code in your main application css code,  or go to Flex SDK\frameworks\projects\datavisualization and compile the data_management.css into a swf and load it at runtime – this is a better choice if using modules. This error has been around since Flex 3 and if you try and compile the swc by changing the css, you will loose the swz and the ability to cache in flash player.

Fix (add to CSS, this is the basics required for the most part ):

mx|AdvancedDataGrid{
columnDropIndicatorSkin: ClassReference("mx.skins.halo.DataGridColumnDropIndicator");
columnResizeSkin: ClassReference("mx.skins.halo.DataGridColumnResizeSkin");
headerColors: #FFFFFF, #E6E6E6;
headerDragProxyStyleName: "headerDragProxyStyle";
headerBackgroundSkin: ClassReference("mx.skins.halo.DataGridHeaderBackgroundSkin");
headerSeparatorSkin: ClassReference("mx.skins.halo.DataGridHeaderSeparator");
headerHorizontalSeparatorSkin: ClassReference("mx.skins.halo.AdvancedDataGridHeaderHorizontalSeparator");
headerStyleName: "advancedDataGridStyles";
sortArrowSkin: ClassReference("mx.skins.halo.DataGridSortArrow");
stretchCursor: Embed(source="Assets.swf",symbol="cursorStretch");
}
 
mx|AdvancedDataGridSortItemRenderer{
paddingTop: 0;
paddingBottom: 0;
paddingLeft: 0;
paddingRight: 0;
horizontalGap: 0;
color: #0B333C;
icon: ClassReference("mx.skins.halo.DataGridSortArrow");
}
 
mx|PrintAdvancedDataGrid{
alternatingItemColors: #FFFFFF, #FFFFFF;
borderColor: 0;
columnResizeSkin: ClassReference("mx.skins.halo.DataGridColumnResizeSkin");
headerColors: #FFFFFF, #FFFFFF;
headerSeparatorSkin: ClassReference("mx.skins.halo.DataGridHeaderSeparator");
headerStyleName: "advancedDataGridStyles";
horizontalGridLineColor: 0;
horizontalGridLines: true;
sortArrowSkin: ClassReference("mx.skins.halo.DataGridSortArrow");
stretchCursor: Embed(source="Assets.swf",symbol="cursorStretch");
verticalGridLineColor: #000000;
}
 
mx|PrintOLAPDataGrid{
alternatingItemColors: #FFFFFF, #FFFFFF;
borderColor: 0;
columnResizeSkin: ClassReference("mx.skins.halo.DataGridColumnResizeSkin");
headerColors: #FFFFFF, #FFFFFF;
headerSeparatorSkin: ClassReference("mx.skins.halo.DataGridHeaderSeparator");
headerStyleName: "advancedDataGridStyles";
horizontalGridLineColor: 0;
horizontalGridLines: true;
stretchCursor: Embed(source="Assets.swf",symbol="cursorStretch");
verticalGridLineColor: #000000;
}

This is something that had me  banging my head against the wall and thought I would share. The use case is using the left and right swipe gesture to register against the UIWebView/UIView that then calls a swipe function. For my case I was using it to change navigation on a UITableView, but you could use is for back/forward on the UIWebView itself or use the same process to register custom gestures. Of all the resources I found, they use a UIView over the UIWebView, or a disable interactivity on the UIWebView and then push touch event into it. The code is used inside a UIViewController with a UIWebVIew present.

- (void)viewDidLoad
{
     [super viewDidLoad];
     UISwipeGestureRecognizer *swipeRight = [[UISwipeGestureRecognizer alloc] initWithTarget:self  action:@selector(swipeRightAction:)];
     swipeRight.direction = UISwipeGestureRecognizerDirectionRight;
     swipeRight.delegate = self;
     [webView addGestureRecognizer:swipeRight];
 
     UISwipeGestureRecognizer *swipeLeft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeLeftAction:)];
     swipeLeft.direction = UISwipeGestureRecognizerDirectionLeft;
     swipeLeft.delegate = self;
     [webView addGestureRecognizer:swipeLeft];
}
 
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
     return YES;
}
 
- (void)swipeRightAction:(id)ignored
{
     NSLog(@"Swipe Right");
     //add Function
}
 
- (void)swipeLeftAction:(id)ignored
{
     NSLog(@"Swipe Left");
     //add Function
}

Cairngorm 3 is really just parsley and spicelib with utility libraries that help development and code reuse. Recently on a modular application I wanted to convert the libraries to RSLs, for the benefits of multiple modules leveraging the library without having to compile. This is all good until you actually set the modules to compile with reference to the RSL in the ant environment. I ran into various errors of dependency which i could not figure out for hte life of me until I got down and dirty with the libraries. The order they are associated in will fix the dependency. This may seem simple because if you use Flash builder everything works great, but when using ant it changes dramatically and it is up to the developer to define the build.  So hopefully this will make someones life easier.

Runtime Shared Library implimentation in ant:

<!--  ORDER IS IMPORTANT::DONOT CHANGE -->
    <!-- Reflection api -->
    <runtime-shared-library-path>
<path-element>${lib-dir}/spicelib_flex_2.2.2.swc</path-element>
        <rsl-url>${rsl-url}/spicelib_flex_2.2.2.swf</rsl-url>
<policy-file-url>${crossdomain-url}</policy-file-url>
        <rsl-url>${rsl-url}/spicelib_flex_2.2.2.swf</rsl-url>
<policy-file-url>
        </policy-file-url>
    </runtime-shared-library-path>
 
    <!-- IOC framework for use with metadata  -->
    <runtime-shared-library-path>
<path-element>${lib-dir}/parsley_flex4_2.2.2.swc</path-element>
        <rsl-url>${rsl-url}rsls/parsley_flex4_2.2.2.swf</rsl-url>
<policy-file-url>${crossdomain-url}</policy-file-url>
        <rsl-url>${rsl-url}/parsley_flex4_2.2.2.swf</rsl-url>
<policy-file-url>
        </policy-file-url>
    </runtime-shared-library-path>
 
    <!-- Observe other objects and react to changes in some way and execute view behaviour -->
    <runtime-shared-library-path>
<path-element>${lib-dir}/observerParsley_1.8.swc</path-element>
        <rsl-url>${rsl-url}rsls/observerParsley_1.8.swf</rsl-url>
<policy-file-url>${crossdomain-url}</policy-file-url>
        <rsl-url>${rsl-url}/observerParsley_1.8.swf</rsl-url>
<policy-file-url>
        </policy-file-url>
    </runtime-shared-library-path>
 
    <!--  Simplifies the configuration, rendering and loading of modular content -->
    <runtime-shared-library-path>
<path-element>${lib-dir}/module_0.9.swc</path-element>
        <rsl-url>${rsl-url}rsls/module_0.9.swf</rsl-url>
<policy-file-url>${crossdomain-url}</policy-file-url>
        <rsl-url>${rsl-url}/module_0.9.swf</rsl-url>
<policy-file-url>
        </policy-file-url>
    </runtime-shared-library-path>
 
    <!--  Provides the ability to group validators -->
    <runtime-shared-library-path>
<path-element>${lib-dir}/validation_1.9.swc</path-element>
        <rsl-url>${rsl-url}rsls/validation_1.9.swf</rsl-url>
<policy-file-url>${crossdomain-url}</policy-file-url>
        <rsl-url>${rsl-url}/validation_1.9.swf</rsl-url>
<policy-file-url>
        </policy-file-url>
    </runtime-shared-library-path>

You will also want to create the RSL swf from the swc in ant. Make note the the digest tool. This is extremely import in most cases will be a large issue. The digest is what is used to identify the correct library that the application was compiled against.:

    <!-- Build out rsls library -->
    <macrodef name="create-rsl">
        <attribute name="rsl-dir" />
        <attribute name="swc-dir" />
        <attribute name="swc-name" />
 
        <sequential>
            <unzip src="@{swc-dir}/@{swc-name}.swc"
                dest="@{rsl-dir}">
<patternset>
                    <include name="library.swf" />
                </patternset>
            </unzip>
 
            <!-- optimize  - I use a library config that sets debug false and opt to true,
             also include metadata as shown below. You can also default to the flex-config.xml -->
            <exec executable="${FLEX_HOME}/bin/optimizer.exe"
                failonerror="true">
                <arg line="-input @{rsl-dir}/library.swf" />
                <arg line="-output @{rsl-dir}/@{swc-name}.swf" />
                <arg line="-load-config configs/library-config.xml" />
            </exec>
 
            <!-- most important part that is not completely documented -->
            <delete file="@{rsl-dir}/library.swf" />
            <exec executable="${FLEX_HOME}/bin/digest.exe"
                failonerror="true">
                <arg line="-digest.rsl-file  @{rsl-dir}/@{swc-name}.swf" />
                <arg line="-digest.swc-path  @{swc-dir}/@{swc-name}.swc" />
            </exec>
 
            <!-- copies the swf rsl back into the directory for rsl deployment
            without rebuilding each time -->
            <copy overwrite="true"
                preservelastmodified="true"
                todir="${source.libs}/rsls/">
                <fileset casesensitive="yes"
                    dir="@{rsl-dir}/">
                    <include name="@{swc-name}.swf" />
                </fileset>
            </copy>
        </sequential>
    </macrodef>
 
##USE##
<create-rsl rsl-dir="${output.dir.rsls}"
            swc-dir="${source.libs}/library/"
            swc-name="componentLibrary" />

Another key to using RSLs that leverage the parsley metadata is to make sure when you compile that you are keeping the metadata:

 <keep-as3-metadata>
            <name>Metadata</name>
            <name>DefaultProperty</name>
            <name>Required</name>
            <name>Event</name>
            <name>AssignableTo</name>
            <name>Inject</name>
            <name>InjectConstructor</name>
            <name>Factory</name>
            <name>Init</name>
            <name>Destroy</name>
            <name>Observe</name>
            <name>AsyncInit</name>
            <name>ManagedEvents</name>
            <name>MessageDispatcher</name>
            <name>MessageHandler</name>
            <name>MessageBinding</name>
            <name>MessageInterceptor</name>
            <name>MessageError</name>
            <name>Command</name>
            <name>CommandResult</name>
            <name>CommandError</name>
            <name>CommandStatus</name>
            <name>ResourceBinding</name>
            <name>Selector</name>
            <name>Target</name>
            <name>Internal</name>
            <name>ObjectDefinition</name>
        </keep-as3-metadata>