/**
* Used as a containing clip for many children display objects that need to be sorted visually based on a certain property.
*
* Author:
* Nate Chatellier, e-mail: natejc@natejc.com
*
* @see http://blog.natejc.com
*
* Released under the MIT License:
* Copyright (c) 2010 Nate Chatellier
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.natejc.display
{
import flash.display.DisplayObject;
import flash.display.Sprite;
import flash.events.Event;
/**
* Used as a containing clip for many children display objects that need to be sorted visually based on a certain property.
*
* @author Nate Chatellier
*/
public class SpriteAutoSorter extends Sprite
{
/** The property of the display object that should be used to sort on. */
public var sPropertyToSortOn :String = "y";
/** Stores a reference to all child display objects contained by this clip. */
protected var _aChildren :Array = [];
/** References how many children are thought to be contained by this display object. This is used for protection of something not being accurate and for speed. */
protected var _nNumChildren :int = 0;
/* ---------------------------------------------------------------------------------------- */
public function SpriteAutoSorter()
{
super();
}
/* ---------------------------------------------------------------------------------------- */
/**
* Makes this Sprite begin sorting every frame.
*/
public function beginSorting():void
{
this.addEventListener(Event.ENTER_FRAME, update);
}
/* ---------------------------------------------------------------------------------------- */
/**
* Stop this Sprite from sorting every frame (saves on cpu usage).
*/
public function stopSorting():void
{
this.removeEventListener(Event.ENTER_FRAME, update);
}
/* ---------------------------------------------------------------------------------------- */
/**
* Makes sure all display objects contained within this clip are sorted.
*
* @param $e The dispatched Event.ENTER_FRAME event.
*/
protected function update($e:Event = null):void
{
if (_nNumChildren != this.numChildren)
this.rebuildChildArray();
this.sort();
}
/* ---------------------------------------------------------------------------------------- */
/**
* @private
* Sorts all display objects contained within this clip based on the attribute specified by sPropertyToSortOn.
*/
protected function sort():void
{
_aChildren.sortOn(sPropertyToSortOn, Array.NUMERIC);
for (var i:int = 0; i < _nNumChildren; i++)
this.setChildIndex(_aChildren[i], i);
}
/* ---------------------------------------------------------------------------------------- */
/**
* @private
* Ensures the array that is used to sort the display objects is accurate.
*/
protected function rebuildChildArray():void
{
_aChildren = [];
for (var i:int = 0; i < this.numChildren; i++)
_aChildren.push(this.getChildAt(i));
_nNumChildren = this.numChildren;
}
/* ---------------------------------------------------------------------------------------- */
/**
* Adds a child DisplayObject instance to this clip. The child is automatically sorted based on sPropertyToSortOn.
*
* @param $mcChild The DisplayObject instance to add as a child of this DisplayObjectContainer instance.
* @return The DisplayObject instance that you pass in the child parameter or null if it was already a child of this clip.
*/
override public function addChild($mcChild:DisplayObject):DisplayObject
{
if (_aChildren.indexOf($mcChild) < 0) // ensure the object isn't already in the array
{
super.addChild($mcChild);
_aChildren.push($mcChild);
_nNumChildren++;
this.sort();
return $mcChild;
}
return null;
}
/* ---------------------------------------------------------------------------------------- */
/**
* Removes the specified DisplayObject instance from this clip..
*
* @param $mcChild The DisplayObject instance that is to be removed.
* @return The DisplayObject instance that you pass in the child parameter or null if it was not a child of this clip.
*/
override public function removeChild($mcChild:DisplayObject):DisplayObject
{
var nIndexOfChild:int = _aChildren.indexOf($mcChild);
if (nIndexOfChild < 0) // return null if $mcChild is not a child of this clip
return null;
super.removeChild($mcChild);
_aChildren.splice(nIndexOfChild, 1);
_nNumChildren--;
this.sort();
return $mcChild;
}
/* ---------------------------------------------------------------------------------------- */
}
}