DZone Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

Charlie has posted 2 posts at DZone. View Full User Profile

DeclarativeDescriptor An Example Of Writing A Custom DataDescriptor

06.19.2008
| 5664 views |
  • submit to reddit
        
Sometimes it becomes necessary to write a custom DataDescriptor for certain Flex controls (i.e. Tree, TreeMap, etc).  This is a generic data descriptor that allows you to declare a single field name to be used for the children of the given node.  This makes it easy to simple tell Flex to use any field instead of the default "children" field.

package {
	
	import mx.collections.ArrayCollection;
	import mx.collections.CursorBookmark;
	import mx.collections.ICollectionView;
	import mx.collections.IViewCursor;
	import mx.controls.treeClasses.ITreeDataDescriptor;
	import mx.events.CollectionEvent;
	import mx.events.CollectionEventKind;
	
	public class DeclarativeDescriptor implements ITreeDataDescriptor {
		
		private var _fieldname : String;
		
		public function DeclarativeDescriptor( fieldname : String ) {
			_fieldname = fieldname;
		}

		public function getChildren(node:Object, model:Object=null) : ICollectionView {
			if( node.hasOwnProperty( _fieldname ) ) {
				return node[_fieldname] is ICollectionView ? node[_fieldname] as ICollectionView : new ArrayCollection( node[_fieldname] );
			} else {
				return null;
			}
		}
		
		public function hasChildren(node:Object, model:Object=null) : Boolean {
			if( isBranch( node, model ) ) {
				var children : ICollectionView = getChildren( node, model );
				return children.length > 0;
			} else {
				return false;
			}
		}
		
		public function isBranch(node:Object, model:Object=null) : Boolean {
			return node.hasOwnProperty(_fieldname);
		}
		
		public function getData(node:Object, model:Object=null) : Object {
			return node;
		}
		
		public function addChildAt(parent:Object, child:Object, index:int, model:Object=null) : Boolean {
	        var event:CollectionEvent = new CollectionEvent(CollectionEvent.COLLECTION_CHANGE);
	        event.kind = CollectionEventKind.ADD;
	        event.items = [child];
	        event.location = index;
	        if (!parent) {
	            var iterator:IViewCursor = model.createCursor();
	            iterator.seek(CursorBookmark.FIRST, index);
	            iterator.insert(child);
	        } else if (parent is Object) {
	            if (isBranch(parent) ) {
	            	var children : Object = parent[_fieldname];
	                if( children is ArrayCollection) {
	                    children.addItemAt(child, index);
	                    if (model) {
	                        model.dispatchEvent(event);
	                        model.itemUpdated(parent);
	                    }
	                    return true;
	                } else {
	                    children.splice(index, 0, child);
	                    if (model)
	                        model.dispatchEvent(event);
	                    return true;
	                }
	            }
	        }
	        return false;
		}
		
		public function removeChildAt(parent:Object, child:Object, index:int, model:Object=null) : Boolean {
	        var event:CollectionEvent = new CollectionEvent(CollectionEvent.COLLECTION_CHANGE);
	        event.kind = CollectionEventKind.REMOVE;
		    event.items = [child];
		    event.location = index;
		
		    //handle top level where there is no parent
		    if (!parent) {
		        var iterator:IViewCursor = model.createCursor();
		        iterator.seek(CursorBookmark.FIRST, index);
		        iterator.remove();
		        if (model)
		            model.dispatchEvent(event);
		        return true;
		    } else if (parent is Object) {
		    	var children : Object = parent[_fieldname];
		        if (children) {
		            children.splice(index, 1);
		            if (model) 
		                model.dispatchEvent(event);
		            return true;
		        }
		    }
		    return false;
		}
	}
}