]> git.mjollnir.org Git - moodle.git/blob
346e88d0fe49ed3344be8d2f8f19b74b2eea3ae5
[moodle.git] /
1 package flare.animate.interpolate
2 {
3         import flare.util.Property;
4         
5         import flash.utils.getDefinitionByName;
6         import flash.utils.getQualifiedClassName;
7         
8         /**
9          * Base class for value interpolators. This class also provides factory 
10          * methods for creating concrete interpolator instances -- see the
11          * <code>create</code> method for details about interpolator creation.
12          */
13         public class Interpolator
14         {
15                 /** The target object whose property is being interpolated. */
16                 protected var _target:Object;
17                 /** The property to interpolate. */
18                 protected var _prop:Property;
19                 
20                 /**
21                  * Base constructor for Interpolator instances.
22                  * @param target the object whose property is being interpolated
23                  * @param property the property to interpolate
24                  * @param value the target value of the interpolation
25                  */
26                 public function Interpolator(target:Object, property:String,
27                                                                          start:Object, end:Object)
28                 {
29                         reset(target, property, start, end);
30                 }
31                 
32                 /**
33                  * Re-initializes an exising interpolator instance.
34                  * @param target the object whose property is being interpolated
35                  * @param property the property to interpolate
36                  * @param value the target value of the interpolation
37                  */
38                 public function reset(target:Object, property:String,
39                                       start:Object, end:Object):void
40                 {
41                         _target = target;
42                         _prop = Property.$(property);
43                         init(start, end);
44                 }
45                 
46                 /**
47                  * Performs initialization of an interpolator, typically by
48                  * initializing the start and ending values. Subclasses should
49                  * override this method for custom initialization.
50                  * @param value the target value of the interpolation
51                  */
52                 protected function init(start:Object, end:Object) : void
53                 {
54                         // for subclasses to override
55                 }
56                 
57                 /**
58                  * Calculate and set an interpolated property value. Subclasses should
59                  * override this method to implement custom interpolation routines.
60                  * @param f the interpolation fraction (typically between 0 and 1)
61                  */
62                 public function interpolate(f:Number) : void
63                 {
64                         throw new Error("This is an abstract method");
65                 }
66                 
67                 // -- Interpolator Factory --------------------------------------------
68                 
69                 private static var _maxPoolSize:int = 10000;
70                 private static var _pools:Object = [];
71                 private static var _lookup:Object = buildLookupTable();
72                 private static var _rules:Array = buildRules();
73                 
74                 private static function buildLookupTable() : Object
75                 {                       
76                         // add variables to ensure classes are included by compiler
77                         var ni:NumberInterpolator;
78                         var di:DateInterpolator;
79                         var pi:PointInterpolator;
80                         var ri:RectangleInterpolator;
81                         var mi:MatrixInterpolator;
82                         var ai:ArrayInterpolator;
83                         var ci:ColorInterpolator;
84                         var oi:ObjectInterpolator;
85                         
86                         // build the value->interpolator lookup table
87                         var lut:Object = new Object();
88                         lut["Number"] = "flare.animate.interpolate::NumberInterpolator";
89                         lut["int"] = "flare.animate.interpolate::NumberInterpolator";
90                         lut["Date"] = "flare.animate.interpolate::DateInterpolator";
91                         lut["Array"] = "flare.animate.interpolate::ArrayInterpolator";
92                         lut["flash.geom::Point"] = "flare.animate.interpolate::PointInterpolator";
93                         lut["flash.geom::Rectangle"] = "flare.animate.interpolate::RectangleInterpolator";
94                         lut["flash.geom::Matrix"] = "flare.animate.interpolate::MatrixInterpolator";
95                         return lut;
96                 }
97                 
98                 private static function buildRules() : Array
99                 {
100                         var rules:Array = new Array();
101                         rules.push(isColor);
102                         rules.push(isShape);
103                         return rules;
104                 }
105                 
106                 private static function isColor(target:Object, property:String, s:Object, e:Object)
107                         : String
108                 {
109                         return property.indexOf("Color")>=0 || property.indexOf("color")>=0
110                                 ? "flare.animate.interpolate::ColorInterpolator"
111                                 : null;
112                 }
113                 
114                 private static function isShape(target:Object, property:String, s:Object, e:Object)
115                         : String
116                 {
117                         return property == "shape"
118                                 ? "flare.animate.interpolate::ObjectInterpolator"
119                                 : null;
120                 }
121                 
122                 /**
123                  * Extends the interpolator factory with a new interpolator type.
124                  * @param valueType the fully qualified class name for the object type
125                  *  to interpolate
126                  * @param interpType the fully qualified class name for the
127                  *  interpolator class type
128                  */
129                 public static function addInterpolatorType(valueType:String, interpType:String) : void
130                 {
131                         _lookup[valueType] = interpType;
132                 }
133                                 
134                 /**
135                  * Clears the lookup table of interpolator types, removing all
136                  * type to interpolator mappings.
137                  */
138                 public static function clearInterpolatorTypes():void
139                 {
140                         _lookup = new Object();
141                 }
142                 
143                 /**
144                  * Adds a rule to the interpolator factory. The input function should
145                  * take a target object, property name string, and target value as
146                  * arguments and either return a fully qualified class name for the
147                  * type of interpolator to use, or null if this rule does not apply.
148                  * @param f the rule function for supplying custom interpolator types
149                  *  based on contextual conditions
150                  */
151                 public static function addInterpolatorRule(f:Function):void
152                 {
153                         _rules.push(f);
154                 }
155                 
156                 /**
157                  * Clears all interpolator rule functions from the interpolator
158                  * factory.
159                  */
160                 public static function clearInterpolatorRules():void
161                 {
162                         _rules = new Array();
163                 }
164                 
165                 /**
166                  * Returns a new interpolator instance for the given target object,
167                  * property name, and interpolation target value. This factory method
168                  * follows these steps to provide an interpolator instance:
169                  * <ol>
170                  *  <li>The list of installed interpolator rules is consulted, and if a
171                  *      rule returns a non-null class name string, an interpolator of
172                  *      that type will be returned.</li>
173                  *  <li>If all rules return null values, then the class type of the
174                  *      interpolation value is used to look up the appropriate
175                  *      interpolator type for that value. If a matching interpolator
176                  *      type is found, an interpolator is initialized and returned.
177                  *      </li>
178                  *  <li>If no matching type is found, a default ObjectInterpolator
179                  *      instance is initialized and returned.</li>
180                  * </ol>
181                  * 
182                  * <p>By default, the interpolator factory contains two rules. The
183                  * first rule returns the class name of ColorInterpolator for any
184                  * property names containing the string "color" or "Color". The second
185                  * rule returns the class name of ObjectInterpolator for the property
186                  * name "shape".</p>
187                  * 
188                  * <p>The default value type to interpolator type mappings are:
189                  * <ul>
190                  *  <li><code>Number -> NumberInterpolator</code></li>
191                  *  <li><code>int -> NumberInterpolator</code></li>
192                  *  <li><code>Date -> DateInterpolator</code></li>
193                  *  <li><code>Array -> ArrayInterpolator</code></li>
194                  *  <li><code>flash.geom.Point -> PointInterpolator</code></li>
195                  *  <li><code>flash.geom.Rectangle -> RectangleInterpolator</code></li>
196                  * </ul>
197                  * </p>
198                  * 
199                  * <p>The interpolator factory can be extended either by adding new
200                  * interpolation rule functions or by adding new mappings from
201                  * interpolation value types to custom interpolator classes.</p>
202                  */
203                 public static function create(target:Object, property:String,
204                                                   start:Object, end:Object): Interpolator
205                 {
206                         // first, check the rules list for an interpolator
207                         var name:String = null;
208                         for (var i:uint=0; name==null && i<_rules.length; ++i) {
209                                 name = _rules[i](target, property, start, end);
210                         }
211                         // if no matching rule, use the type lookup table
212                         if (name == null) {
213                                 name = _lookup[getQualifiedClassName(end)];
214                         }
215                         // if that fails, use ObjectInterpolator as default
216                         if (name == null) {
217                                 name = "flare.animate.interpolate::ObjectInterpolator";
218                         }
219                         
220                         // now create the interpolator, recycling from the pool if possible
221                         var pool:Array = _pools[name] as Array;
222                         if (pool == null || pool.length == 0) {
223                                 // nothing in the pool, create a new instance
224                                 var Ref:Class = getDefinitionByName(name) as Class;
225                                 return new Ref(target, property, start, end) as Interpolator;
226                         } else {
227                                 // reuse an interpolator from the object pool
228                                 var interp:Interpolator = pool.pop() as Interpolator;
229                                 interp.reset(target, property, start, end);
230                                 return interp;
231                         }
232                 }
233                 
234                 /**
235                  * Reclaims an interpolator for later recycling. The reclaimed
236                  * interpolator should not be in active use by any other classes.
237                  * @param interp the Interpolator to reclaim
238                  */
239                 public static function reclaim(interp:Interpolator):void
240                 {
241                         var type:String = getQualifiedClassName(interp); 
242                         var pool:Array = _pools[type] as Array;
243                         if (pool == null) {
244                                 _pools[type] = [interp];
245                         } else if (pool.length < _maxPoolSize) {
246                                 pool.push(interp);
247                         }
248                 }
249                 
250         } // end of class Interpolator
251 }