I guess this week is my week for creating AS3/Flex hacks. I created an XML encoder/decoder that will accept a class-map and create your model from your XML and visa-versa. As part of that I have display objects as part of the model that needs saving out. I suppose you could liken it to MXML.
In order for the XML encoder to work with DisplayObjectContainers I had to give it a way to work with an ArrayCollection to add or remove the children. So I subclassed LayoutContainer and gave it a property called "children" which is an ArrayCollection. Then I set up as a listener to it and every time something is added or removed I use the corresponding DisplayObjectContainer methods to update the display. Pretty slick! The only downside is that someone could add anything to the children ArrayCollection and break things since I am expecting DisplayObjects only. I could add error checking and make it fix itself when that happens... maybe another time.
Here's my listener which responds to the "collectionChange" event of children:
{
var i:Number;
var items:Array = event.items;
var location:Number = event.location;
var oldLocation:Number = event.oldLocation;
var numItems:Number = items.length;
var child:DisplayObject;
var propChange:PropertyChangeEvent;
switch (event.kind)
{
case CollectionEventKind.ADD:
for (i = 0; i <numItems; i++)
{
child = items[i] as DisplayObject;
if (child)
addChildAt(child, location + i);
}
break;
case CollectionEventKind.REMOVE:
for (i = 0; i <numItems; i++)
{
child = items[i];
if (child)
removeChild(child);
}
break;
case CollectionEventKind.MOVE:
setChildIndex(getChildAt(oldLocation), location);
break;
case CollectionEventKind.REPLACE:
for (i = 0; i <numItems; i++)
{
propChange = items[i] as PropertyChangeEvent;
var oldChild:DisplayObject = propChange.oldValue as DisplayObject;
var newChild:DisplayObject = propChange.newValue as DisplayObject;
if (oldChild && newChild)
{
var index:Number = getChildIndex(oldChild);
removeChildAt(index);
addChildAt(newChild, index);
}
}
break;
case CollectionEventKind.REFRESH:
removeAllChildren();
for each (child in _children)
addChild(child);
break;
case CollectionEventKind.RESET:
removeAllChildren();
for each (child in _children)
addChild(child);
break;
case CollectionEventKind.UPDATE:
// don't need to do anything
break;
}
}