/** * com.sekati.utils.ClassUtils * @version 2.2.0 * @author jason m horwitz | sekati.com * Copyright (C) 2007 jason m horwitz, Sekat LLC. All Rights Reserved. * Released under the MIT License: http://www.opensource.org/licenses/mit-license.php */ import com.sekati.core.KeyFactory; /** * Static class for wrapping various Class utilities. For example linking 'extend MovieClip' type * classes to MovieClips thru attachMovie, createEmptyMovieClip or MovieClip Instances on stage.

* * An initObject param is available in methods: {@link #createEmptyMovieClip}, {@link #attachMovie} * and {@link #attachClass}. _depth is a custom initObject param which will set the clip to this depth * regardless of method but *will not* store _depth as a MovieClip property; use getDepth if needed. * * {@code Example Class: * class com.sekati.Test extends MovieClip { * public function Test(){ * trace("Test Class instantiated on: "+this._name); * } * } * } * * @TODO Add an AS2 Class index getter for debugging purposes. */ class com.sekati.utils.ClassUtils { /** * create a movieclip with linked class (various init options) * @param classRef (Function) reference to class to attach * @param target (MovieClip) target scope to create MovieClip * @param instanceName (String) created MovieClip instance name * @param initObject (Object) object of properties to create MovieClip with. Depth will automatically be created if none is specified * @return MovieClip * {@code Usage: * var mc0:MovieClip = ClassUtils.createEmptyMovieClip (com.sekati.Test, this, "mc0"); * var mc0:MovieClip = ClassUtils.createEmptyMovieClip (com.sekati.Test, _root, "mc0", {_depth: 100, _x:25, _y:25}); * var mc0:MovieClip = ClassUtils.createEmptyMovieClip (com.sekati.Test, this, "mc0", {_x:25, _y:25}); * } */ public static function createEmptyMovieClip(classRef:Function, target:MovieClip, instanceName:String, initObject:Object):MovieClip { var depth:Number = (!initObject._depth) ? target.getNextHighestDepth( ) : initObject._depth; var mc:MovieClip = target.createEmptyMovieClip( instanceName, depth ); mc.__proto__ = classRef.prototype; if (initObject) { for (var i in initObject) { if (i != "_depth") { mc[i] = initObject[i]; } } } classRef.apply( mc ); KeyFactory.inject( mc ); return mc; } /** * attach a MovieClip from library and extend with class (various init options) * @param classRef (Function) reference to class to attach * @param target (MovieClip) target scope to create MovieClip * @param idName (String) linkage id for exported MovieClip in library * @param instanceName (String) created MovieClip instance name * @param initObject (Object) object of properties to create MovieClip with. Depth will automatically be created if none is specified * @return MovieClip * {@code Usage: * var mc1:MovieClip = ClassUtils.attachMovie (com.sekati.Test, _root, "linkedMc", "mc1"); * var mc1:MovieClip = ClassUtils.attachMovie (com.sekati.Test, _root, "linkedMc", "mc1", {_x:50, _y:50}); * var mc1:MovieClip = ClassUtils.attachMovie (com.sekati.Test, _root, "linkedMc", "mc1", {_depth:200, _x:50, _y:50}); * } */ public static function attachMovie(classRef:Function, target:MovieClip, idName:String, instanceName:String, initObject:Object):MovieClip { var depth:Number = (!initObject._depth) ? target.getNextHighestDepth( ) : initObject._depth; var mc:MovieClip = target.attachMovie( idName, instanceName, depth, initObject ); mc.__proto__ = classRef.prototype; if (mc._depth) { delete mc._depth; } classRef.apply( mc ); KeyFactory.inject( mc ); return mc; } /** * Attach a movie from a DLL swf's library (loads dll then attaches requested movie). * NOTE: you should insert a delay between your callback and methods calls in the shared library as it initializes. * @param dll (Function) url of the dll.swf which contains exported assets in its library * @param target (MovieClip) target scope to attachMovie within * @param idName (String) linkage id for exported MovieClip in library * @param instanceName (String) created MovieClip instance name * @param initObject (Object) object of properties to create MovieClip with. Depth will automatically be created if none is specified * @param cb (Function) callback function to fire when dll has been loaded and clip attached * @return MovieClip * {@code Usage: * var mc0:MovieClip = ClassUtils.attachDllMovie("dll.swf", _root, "myDllExportedItem", "mc0", {_x:50, _y:50, _depth:20}, myCallBackFn); * } */ public static function attachDllMovie(dll:String, target:MovieClip, idName:String, instanceName:String, initObject:Object, cb:Function):MovieClip { var depth:Number = (!initObject._depth) ? target.getNextHighestDepth( ) : initObject._depth; var mc:MovieClip = target.createEmptyMovieClip( instanceName, depth ); var mcLoader:MovieClipLoader = new MovieClipLoader( ); var onDLLLoaded:Function = function():Void { mcLoader.removeListener( listener ); if(cb) _global['setTimeout']( this, 'cb', 50 ); }; var listener:Object = new Object( ); listener.onLoadInit = function(mc:MovieClip):Void { mc.attachMovie( idName, instanceName, mc.getNextHighestDepth( ) ); target[instanceName] = target[instanceName][instanceName]; if (initObject) { for (var i in initObject) { if (i != "_depth") mc[i] = initObject[i]; } } onDLLLoaded( ); }; mcLoader.addListener( listener ); mcLoader.loadClip( dll, mc ); return mc; } /** * extend a MovieClip instance (on stage) with class (various init options) * @param classRef (Function) reference to class to attach * @param target (MovieClip) target scope to create MovieClip * @param initObject (Object) object of properties to create MovieClip with. Depth will automatically be created if none is specified * @return MovieClip * {@code Usage: * var mc2:MovieClip = ClassUtils.attachClass (com.sekati.Test, mc2); * var mc2:MovieClip = ClassUtils.attachClass (com.sekati.Test, _root.mc2, {_x:75, _y:75}); * var mc2:MovieClip = ClassUtils.attachClass (com.sekati.Test, mc2, {_depth:300, _x:75, _y:75}); * } */ public static function attachClass(classRef:Function, target:MovieClip, initObject:Object):MovieClip { var mc:MovieClip = target; mc.__proto__ = classRef.prototype; if (initObject) { for (var i in initObject) { if (i != "_depth") { mc[i] = initObject[i]; } else { target.swapDepths( initObject[i] ); } } } classRef.apply( mc ); KeyFactory.inject( mc ); return target; } /** * Create and return a new instance of a defined class * @param classRef (Function) reference to full class namespace * @param args (Array) array of constructor arguments * @return Object - instantiated class object * {@code Usage: * var o:Point = ClassUtils.createInstance (com.sekati.geom.Point, [15,50]); * } */ public static function createInstance(classRef:Function, args:Array):Object { var o:Object = {__constructor__:classRef, __proto__:classRef.prototype}; classRef.apply( o, args ); KeyFactory.inject( o ); return o; } /** * Create and return a new instance of a defined class without * invoking its constructor * @param classRef (Function) reference to full class namespace * @return Object - class object * {@code Usage: * var scr:Scroll = ClassUtils.createCleanInstance(com.sekati.ui.Scroll); * } */ public static function createCleanInstance(classRef:Function):Object { var o:Object = new Object; o.__proto__ = classRef.prototype; o.__constructor__ = classRef; KeyFactory.inject( o ); return o; } /** * Check if a subclass is extended by a superclass * @param subclassRef (Function) reference to the full subclass namespace * @param superclassRef (Function) reference to the full superclass namespace * @return Boolean * {@code Usage: * trace(ClassUtils.isSubclassOf(com.sekati.display.AbstractClip, com.sekati.display.CoreClip)); // returns: true * } */ public static function isSubclassOf(subclassRef:Function, superclassRef:Function):Boolean { var o:Object = subclassRef.prototype; while(o !== undefined) { o = o.__proto__; if(o === superclassRef.prototype) { return true; } } return false; } /** * Check if a class implements an interface * @param classRef (Function) reference to the full class namespace * @param interfaceRef (Function) reference to the full interface namespace * @return Boolean * {@code Usage: * trace(ClassUtils.isImplementationOf(com.sekati.display.CoreClip, com.sekati.display.ICoreClip)); // returns: true * } */ public static function isImplementationOf(classRef:Function, interfaceRef:Function):Boolean { // interface will not be in prototype chain if(isSubclassOf( classRef, interfaceRef )) { return false; } // if an instance it is not extended, the class has to be an instance of it return (createCleanInstance( classRef ) instanceof interfaceRef); } private function ClassUtils() { } }