1  /*
     2   * Copyright the original author or authors.
     3   * 
     4   * Licensed under the MOZILLA PUBLIC LICENSE, Version 1.1 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   * 
     8   *      http://www.mozilla.org/MPL/MPL-1.1.html
     9   * 
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  /**
    18   * {@code Delegate} offers with {@link Delegate#createDelegate} a method for
    19   * using old-style Template classes.
    20   * 
    21   * <p>Using event handling like in common MovieClips creates problems in OOP
    22   * ActionScript due to the fact that it uses functions as event executions 
    23   * without minding about that the scope always refers to the MovieClip.
    24   * {@code Delegate.createDelegate} allows a proper Workaround for the redirection
    25   * of such methods to a proper different scope.
    26   * 
    27   * <p>Example:
    28   * 
    29   * <p>Test class:
    30   * <code>
    31   *   class com.domain.MyMovieClipController {
    32   *     private var content:String;
    33   *     
    34   *     public function MyMovieClipController(content:String) {
    35   *       this.content = content;
    36   *     }
    37   *     
    38   *     public function onEnterFrame() {
    39   *       trace(content);
    40   *     }
    41   *   }
    42   * </code>
    43   * 
    44   * <p>Usage:
    45   * <code>
    46   *   import com.domain.MyMovieClipController;
    47   *   import org.as2lib.env.reflect.Delegate;
    48   *  
    49   *   var mc:MyMovieClipController = new MyMovieClipController("Hello World!");
    50   *   
    51   *   // Following will not work because of the wrong scope
    52   *   _root.onEnterFrame = mc.onEnterFrame;
    53   *   
    54   *   // Workaround using delegate
    55   *   _root.onEnterFrame = Delegate.create(mc, onEnterFrame);
    56   * </code>
    57   * 
    58   * @author Martin Heidegger
    59   * @version 1.0
    60   */
    61  class org.as2lib.env.reflect.Delegate {
    62  	
    63  	/**
    64  	 * Creates a method that delegates its arguments to a certain scope.
    65  	 * 
    66  	 * @param scope Scope to be used by calling this method.
    67  	 * @param method Method to be executed at the scope.
    68  	 * @return Function that delegates its call to a different scope & method.
    69  	 */
    70  	public static function create(scope, method:Function):Function {
    71  		var result:Function;
    72  		result = function() {
    73  			return arguments.callee.method.apply(arguments.callee.scope, arguments);
    74  		};
    75  		result.scope = scope;
    76  		result.method = method;
    77  		return result;
    78  	}
    79  	
    80  	/**
    81  	 * Creates a method that delegates its arguments to a certain scope and
    82  	 * uses additional fixed arguments.
    83  	 * 
    84  	 * <p>Example:
    85  	 * <code>
    86  	 *   import org.as2lib.env.reflect.Delegate;
    87  	 *   
    88  	 *   function test(a:String, b:Number, c:String) {
    89  	 *   	trace(a+","+b+","+c);
    90  	 *   }
    91  	 *   
    92  	 *   var delegate:Function = Delegate.createExtendedDelegate(this, test, ["a"]);
    93  	 *   delegate(1,"b"); // will trace "a,1,b"
    94  	 * </code>
    95  	 * 
    96  	 * 
    97  	 * @param scope Scope to be used by calling this method.
    98  	 * @param method Method to be executed at the scope.
    99  	 * @param args Arguments to be used at first position.
   100  	 * @return Function that delegates its call to a different scope & method.
   101  	 * @TODO find better name
   102  	 */
   103  	public static function createExtendedDelegate(scope, method:Function, args:Array):Function {
   104  		var result:Function;
   105  		result = function() {
   106  			return arguments.callee.method.apply(arguments.callee.scope, arguments.callee.args.concat(arguments));
   107  		};
   108  		result.scope = scope;
   109  		result.method = method;
   110  		result.args = args;
   111  		return result;
   112  	}
   113  		
   114  	/**
   115  	 * Private Constructor to prevent instantiation.
   116  	 */
   117  	private function Delegate(Void) {
   118  	}
   119  	
   120  }