package { import flash.display.*; import flash.events.*; // Monitors a specified display object to see when it is added to or // removed from the Stage, and broadcasts the correspoding custom events // actionscript_util_StageDetector.ADDED_TO_STAGE and actionscript_util_StageDetector.REMOVED_FROM_STAGE. // USAGE: // var stageDetector:actionscript_util_StageDetector = new actionscript_util_StageDetector(someDisplayObject); // stageDetector.addEventListener(actionscript_util_StageDetector.ADDED_TO_STAGE, // addedToStageListenerFunction); // stageDetector.addEventListener(actionscript_util_StageDetector.REMOVED_FROM_STAGE, // removedFromStageListenerFunction); public class actionscript_util_StageDetector extends EventDispatcher { // Event constants public static const ADDED_TO_STAGE:String = "ADDED_TO_STAGE"; public static const REMOVED_FROM_STAGE:String = "REMOVED_FROM_STAGE"; // The object for which ADDED_TO_STAGE and REMOVED_FROM_STAGE events // will be generated private var watchedObject:DisplayObject = null; // The root of the display hierarchy that contains watchedObject private var watchedRoot:DisplayObject = null; // Flag indicating whether watchedObject is currently on the // display list private var onStage:Boolean = false; // Constructor public function actionscript_util_StageDetector (objectToWatch:DisplayObject) { // Begin monitoring the specified object setWatchedObject(objectToWatch); } // Begins monitoring the specified object to see when it is added to or // removed from the display list public function setWatchedObject (objectToWatch:DisplayObject):void { // Store the object being monitored watchedObject = objectToWatch; // Note whether watchedObject is currently on the display list if (watchedObject.stage != null) { onStage = true; } // Find the root of the display hierarchy containing the // watchedObject, and register with it for ADDED/REMOVED events. // By observing where watchedObject's root is added and removed, // we'll determine whether watchedObject is on or off the // display list. setWatchedRoot(findWatchedObjectRoot()); } // Returns a reference to the object being monitored public function getWatchedObject ():DisplayObject { return watchedObject; } // Frees this actionscript_util_StageDetector object's resources. Call this method before // discarding a actionscript_util_StageDetector object. public function dispose ():void { clearWatchedRoot(); watchedObject = null; } // Handles Event.ADDED events targeted at the root of // watchedObject's display hierarchy private function addedListener (e:Event):void { // If the current watchedRoot was added... if (e.eventPhase == EventPhase.AT_TARGET) { // ...check if watchedObject is now on the display list if (watchedObject.stage != null) { // Note that watchedObject is now on the display list onStage = true; // Notify listeners that watchedObject is now // on the display list dispatchEvent(new Event(actionscript_util_StageDetector.ADDED_TO_STAGE)); } // watchedRoot was added to another container, so there's // now a new root of the display hierarchy containing // watchedObject. Find that new root, and register with it // for ADDED and REMOVED events. setWatchedRoot(findWatchedObjectRoot()); } } // Handles Event.REMOVED events for the root of // watchedObject's display hierarchy private function removedListener (e:Event):void { // If watchedObject is on the display list... if (onStage) { // ...check if watchedObject or one of its ancestors was removed var wasRemoved:Boolean = false; var ancestor:DisplayObject = watchedObject; var target:DisplayObject = DisplayObject(e.target); while (ancestor != null) { if (target == ancestor) { wasRemoved = true; break; } ancestor = ancestor.parent; } // If watchedObject or one of its ancestors was removed... if (wasRemoved) { // ...register for ADDED and REMOVED events from the removed // object (which is the new root of watchedObject's display // hierarchy). setWatchedRoot(target); // Note that watchedObject is not on the display list anymore onStage = false; // Notify listeners that watchedObject was removed from the Stage dispatchEvent(new Event(actionscript_util_StageDetector.REMOVED_FROM_STAGE)); } } } // Returns the root of the display hierarchy that currently contains // watchedObject private function findWatchedObjectRoot ():DisplayObject { var watchedObjectRoot:DisplayObject = watchedObject; while (watchedObjectRoot.parent != null) { watchedObjectRoot = watchedObjectRoot.parent; } return watchedObjectRoot; } // Begins listening for ADDED and REMOVED events targeted at the root of // watchedObject's display hierarchy private function setWatchedRoot (newWatchedRoot:DisplayObject):void { clearWatchedRoot(); watchedRoot = newWatchedRoot; registerListeners(watchedRoot); } // Removes event listeners from watchedRoot, and removes // this actionscript_util_StageDetector object's reference to watchedRoot private function clearWatchedRoot ():void { if (watchedRoot != null) { unregisterListeners(watchedRoot); watchedRoot = null; } } // Registers ADDED and REMOVED event listeners with watchedRoot private function registerListeners (target:DisplayObject):void { target.addEventListener(Event.ADDED, addedListener); target.addEventListener(Event.REMOVED, removedListener); } // Unregisters ADDED and REMOVED event listeners from watchedRoot private function unregisterListeners (target:DisplayObject):void { target.removeEventListener(Event.ADDED, addedListener); target.removeEventListener(Event.REMOVED, removedListener); } } }