You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by ah...@apache.org on 2016/06/16 22:59:48 UTC
[31/50] [abbrv] git commit: [flex-asjs] [refs/heads/spark] - Merge
branch 'develop' into spark
http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/77148f4a/frameworks/projects/MX/src/main/flex/mx/resources/ResourceManagerImpl.as
----------------------------------------------------------------------
diff --cc frameworks/projects/MX/src/main/flex/mx/resources/ResourceManagerImpl.as
index ff6f91a,0000000..cfb5245
mode 100644,000000..100644
--- a/frameworks/projects/MX/src/main/flex/mx/resources/ResourceManagerImpl.as
+++ b/frameworks/projects/MX/src/main/flex/mx/resources/ResourceManagerImpl.as
@@@ -1,1441 -1,0 +1,1441 @@@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package mx.resources
+{
+
+import mx.events.FocusEvent;
+
+import org.apache.flex.core.CallLaterBead;
+import org.apache.flex.events.Event;
+import org.apache.flex.events.EventDispatcher;
+import flex.system.DefinitionManager;
+import flex.system.I18NManager;
- COMPILE::AS3
++COMPILE::SWF
+{
+ import flash.system.ApplicationDomain;
+}
+COMPILE::LATER
+{
+ import org.apache.flex.events.IEventDispatcher;
+ import flex.events.TimerEvent;
+ import flash.system.Capabilities;
+ import flash.system.SecurityDomain;
+ import flash.utils.Dictionary;
+ import mx.core.IFlexModuleFactory;
+ import mx.core.Singleton;
+ import mx.events.ModuleEvent;
+ import mx.events.ResourceEvent;
+ import mx.modules.IModuleInfo;
+ import mx.modules.ModuleManager;
+}
+import mx.core.mx_internal;
+import mx.events.FlexEvent;
+import mx.managers.SystemManagerGlobals;
+import mx.utils.StringUtil;
+import org.apache.flex.core.UIBase;
+
+use namespace mx_internal;
+
+/**
+ * @copy mx.resources.IResourceManager#change
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+[Event(name="change", type="flash.events.Event")]
+
+[ExcludeClass]
+
+/**
+ * @private
+ * This class provides an implementation of the IResourceManager interface.
+ * The IResourceManager and IResourceBundle interfaces work together
+ * to provide internationalization support for Flex applications.
+ *
+ * <p>A single instance of this class manages all localized resources
+ * for a Flex application.</p>
+ *
+ * @see mx.resources.IResourceManager
+ * @see mx.resources.IResourceBundle
+ */
+public class ResourceManagerImpl extends EventDispatcher implements IResourceManager
+{
+ include "../core/Version.as";
+
+ //--------------------------------------------------------------------------
+ //
+ // Class variables
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ * The sole instance of the ResourceManager.
+ */
+ private static var instance:IResourceManager;
+
+ //--------------------------------------------------------------------------
+ //
+ // Class methods
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Gets the single instance of the ResourceManagerImpl class.
+ * This object manages all localized resources for a Flex application.
+ *
+ * @return An object implementing IResourceManager.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ public static function getInstance():IResourceManager
+ {
+ if (!instance)
+ instance = new ResourceManagerImpl();
+
+ return instance;
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ public function ResourceManagerImpl()
+ {
+ super();
+
+ if (SystemManagerGlobals.topLevelSystemManagers.length)
+ {
+ if (SystemManagerGlobals.topLevelSystemManagers[0].currentFrame == 1)
+ {
+ ignoreMissingBundles = true;
+ inFrame1 = true;
+ var topSM:UIBase = SystemManagerGlobals.topLevelSystemManagers[0] as UIBase;
+ if (topSM.getBeadByType(CallLaterBead) == null)
+ topSM.addBead(new CallLaterBead());
+ var clb:CallLaterBead = topSM.getBeadByType(CallLaterBead) as CallLaterBead;
+ clb.callLater(enterFrameHandler, null, this);
+ }
+ }
+
+ var info:Object = SystemManagerGlobals.info;
+ // Falcon injects this property and it is always false
+ // We ignore missing bundles because Falcon doesn't
+ // generate fallback bundles like MXMLC;
+ if (!inFrame1)
+ ignoreMissingBundles = info && info.hasOwnProperty("isMXMLC");
+
+ if (info)
+ processInfo(info, false);
+
+ ignoreMissingBundles = info && info.hasOwnProperty("isMXMLC");
+
+ if (SystemManagerGlobals.topLevelSystemManagers.length)
+ SystemManagerGlobals.topLevelSystemManagers[0].
+ addEventListener(FlexEvent.NEW_CHILD_APPLICATION, newChildApplicationHandler);
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Variables
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ *
+ * Whether or ignoreMissingBundles was set in frame 1
+ */
+ private var inFrame1:Boolean = false;
+
+ /**
+ * @private
+ *
+ * Whether or not to throw an error.
+ */
+ private var ignoreMissingBundles:Boolean = false;
+
+ /**
+ * @private
+ *
+ * The dictionary to hold all of the weak reference resource bundles.
+ */
+ COMPILE::LATER
+ private var bundleDictionary:Dictionary;
+
+ /**
+ * @private
+ * A map whose keys are locale strings like "en_US"
+ * and whose values are "bundle maps".
+ * A bundle map is a map whose keys are bundle names
+ * like "SharedResources" and whose values are ResourceBundle instances.
+ * You can get to an individual resource value like this:
+ * localeMap["en_US"]["SharedResources"].content["currencySymbol"]
+ */
+ private var localeMap:Object = {};
+
+ /**
+ * @private
+ * A map whose keys are URLs for resource modules that have been loaded
+ * and whose values are ResourceModuleInfo instances for those modules.
+ */
+ private var resourceModules:Object = {};
+
+ /**
+ * @private
+ */
+ private var initializedForNonFrameworkApp:Boolean = false;
+
+ //--------------------------------------------------------------------------
+ //
+ // Properties
+ //
+ //--------------------------------------------------------------------------
+
+ //----------------------------------
+ // localeChain
+ //----------------------------------
+
+ /**
+ * @private
+ * Storage for the localeChain property.
+ */
+ private var _localeChain:Array /* of String */;
+
+ /**
+ * @copy mx.resources.IResourceManager#localeChain
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ public function get localeChain():Array /* of String */
+ {
+ return _localeChain;
+ }
+
+ /**
+ * @private
+ */
+ public function set localeChain(value:Array /* of String */):void
+ {
+ _localeChain = value;
+
+ update();
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Methods
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ * This method is called by the SystemManager class of an Application
+ * when the application starts.
+ * It is also called by the FlexModuleFactory class of a code module
+ * when that module gets loaded.
+ *
+ * The MXML compiler autogenerated code which set the
+ * "compiledLocales" and "compiledResourceBundleNames" properties
+ * of the info() Object required by the IFlexModuleFactory
+ * interface that these classes implement.
+ * These two properties together indicate which resource bundle
+ * classes the MXML compiler autogenerated and linked into the
+ * application or module.
+ *
+ * The "compiledLocales" property has been set to the locales
+ * which were specified at compile time using the -locale option.
+ * For example, if you compile with -locale=en_US,ja_JP
+ * then the "compiledLocales" property is the array [ "en_US", "ja_JP" ].
+ *
+ * The "compiledResourceBundleNames" property has been set
+ * to the names of the resource bundles which are used by
+ * the application or module, as determined by the compiler
+ * from [ResourceBundle] metadata and ~~Resource() directives.
+ * For example, if the classes in the application or module
+ * declare that they use resource bundles named "core" and "MyApp",
+ * then the "compiledResourceBundleNames" property is the array
+ * [ "core", "MyApp" ].
+ *
+ * The compiler autogenerated a ResourceBundle subclass for each
+ * (locale, bundle name) pair.
+ * For example, with the above locales and bundle names,
+ * there would be four classes:
+ * en_US$core_properties
+ * en_US$MyApp_properties
+ * ja_JP$core_properties
+ * ja_JP$MyApp_properties
+ *
+ * This method creates one instance of each such class
+ * and installs it into the ResourceManager with addResourceBundle().
+ * If a bundle for a given locale and bundle name already exists
+ * in the ResourceManager already exists, it does not get replaced.
+ * This can happen when a code module gets loaded into an application.
+ *
+ * When sub-applications and modules install their resource bundles
+ * they set useWeakReference = true. Any new resource bundles they
+ * create will be weak referenced by the ResourceManager. The
+ * sub-application or module will then provide a hard reference
+ * to the returned Array of resource bundles to keep them from
+ * being garbage collected.
+ */
+ public function installCompiledResourceBundles(
+ applicationDomain:DefinitionManager,
+ locales:Array /* of String */,
+ bundleNames:Array /* of String */,
+ useWeakReference:Boolean = false):Array
+ {
+ //trace("locales", locales);
+ //trace("bundleNames", bundleNames);
+ var bundles:Array = [];
+ var bundleCount:uint = 0;
+ var n:int = locales ? locales.length : 0;
+ var m:int = bundleNames ? bundleNames.length : 0;
+
+ // Loop over the locales.
+ for (var i:int = 0; i < n; i++)
+ {
+ var locale:String = locales[i];
+
+ // Loop over the bundle names.
+ for (var j:int = 0; j < m; j++)
+ {
+ var bundleName:String = bundleNames[j];
+
+ var bundle:IResourceBundle = installCompiledResourceBundle(
+ applicationDomain, locale, bundleName,
+ useWeakReference);
+
+ if (bundle)
+ bundles[bundleCount++] = bundle;
+ }
+ }
+
+ return bundles;
+ }
+
+ /**
+ * @private
+ */
+ private function installCompiledResourceBundle(
+ applicationDomain:DefinitionManager,
+ locale:String, bundleName:String,
+ useWeakReference:Boolean = false):IResourceBundle
+ {
+ var packageName:String = null;
+ var localName:String = bundleName;
+ var colonIndex:int = bundleName.indexOf(":");
+ if (colonIndex != -1)
+ {
+ packageName = bundleName.substring(0, colonIndex);
+ localName = bundleName.substring(colonIndex + 1);
+ }
+
+ // If a bundle with that locale and bundle name already exists
+ // in the ResourceManager, don't replace it.
+ // If we want to install a weakReferenceDictionary then don't rely on
+ // a weak reference dictionary because it may go way when the
+ // application goes away.
+ var resourceBundle:IResourceBundle = getResourceBundleInternal(locale,
+ bundleName,
+ useWeakReference);
+ if (resourceBundle)
+ return resourceBundle;
+
+ // The autogenerated resource bundle classes produced by the
+ // mxmlc and compc compilers have names that incorporate
+ // the locale and bundle name, such as "en_US$core_properties".
+ var resourceBundleClassName:String =
+ locale + "$" + localName + "_properties";
+ if (packageName != null)
+ resourceBundleClassName = packageName + "." + resourceBundleClassName;
+
+ // Find the bundle class by its name.
+ // We do a hasDefinition() check before calling getDefinition()
+ // because getDefinition() will throw an RTE
+ // if the class doesn't exist.
+ var bundleClass:Class = null;
+ if (applicationDomain.hasDefinition(resourceBundleClassName))
+ {
+ bundleClass = Class(applicationDomain.getDefinition(
+ resourceBundleClassName));
+ }
+
+ if (!bundleClass)
+ {
+ resourceBundleClassName = bundleName;
+ if (applicationDomain.hasDefinition(resourceBundleClassName))
+ {
+ bundleClass = Class(applicationDomain.getDefinition(
+ resourceBundleClassName));
+ }
+ }
+
+ // In case we linked against a Flex 2 SWC, look for the old
+ // class name.
+ if (!bundleClass)
+ {
+ resourceBundleClassName = bundleName + "_properties";
+ if (applicationDomain.hasDefinition(resourceBundleClassName))
+ {
+ bundleClass = Class(applicationDomain.getDefinition(
+ resourceBundleClassName));
+ }
+ }
+
+ if (!bundleClass)
+ {
+ if (ignoreMissingBundles)
+ return null;
+
+ throw new Error(
+ "Could not find compiled resource bundle '" + bundleName +
+ "' for locale '" + locale + "'.");
+ }
+
+ // Create a proxy
+ var proxy:ResourceBundleProxy = new ResourceBundleProxy();
+
+ proxy.bundleClass = bundleClass;
+ proxy.useWeakReference = useWeakReference;
+
+ // In case we just created a ResourceBundle from a Flex 2 SWC,
+ // set its locale and bundleName, because the old constructor
+ // didn't used to do this.
+ proxy.locale = locale;
+ proxy.bundleName = bundleName;
+
+ // Add that resource bundle instance to the ResourceManager.
+ resourceBundle = proxy;
+ addResourceBundle(resourceBundle, useWeakReference);
+
+ return resourceBundle;
+ }
+
+ // FocusEvent is used just so we can add a relatedObject
+ private function newChildApplicationHandler(event:FocusEvent):void
+ {
+ var info:Object = event.relatedObject["info"]();
+ var weakReference:Boolean = false;
+ if ("_resourceBundles" in event.relatedObject)
+ weakReference = true;
+
+ // If the application has a "_resourceBundles" object for us to put
+ // the bundles into then we will. Otherwise have the ResourceManager
+ // create a hard reference to the resources.
+ var bundles:Array = processInfo(info, weakReference);
+ if (weakReference)
+ event.relatedObject["_resourceBundles"] = bundles;
+ }
+
+ private function processInfo(info:Object, useWeakReference:Boolean):Array
+ {
+ var compiledLocales:Array = info["compiledLocales"];
+
+ ResourceBundle.locale =
+ compiledLocales != null && compiledLocales.length > 0 ?
+ compiledLocales[0] :
+ "en_US";
+
- COMPILE::AS3
++ COMPILE::SWF
+ {
+ var applicationDomain:DefinitionManager = new DefinitionManager(info["currentDomain"]);
+ }
+ COMPILE::JS
+ {
+ var applicationDomain:DefinitionManager = new DefinitionManager();
+ }
+
+ var compiledResourceBundleNames:Array /* of String */ =
+ info["compiledResourceBundleNames"];
+
+ var bundles:Array = installCompiledResourceBundles(
+ applicationDomain, compiledLocales, compiledResourceBundleNames,
+ useWeakReference);
+
+ // If the localeChain wasn't specified in the FlashVars of the SWF's
+ // HTML wrapper, or in the query parameters of the SWF URL,
+ // then initialize it to the list of compiled locales,
+ // sorted according to the system's preferred locales as reported by
+ // Capabilities.languages or Capabilities.language.
+ // For example, if the applications was compiled with, say,
+ // -locale=en_US,ja_JP and Capabilities.languages reports [ "ja-JP" ],
+ // set the localeChain to [ "ja_JP" "en_US" ].
+ if (!localeChain)
+ initializeLocaleChain(compiledLocales);
+
+ return bundles;
+ }
+
+ /**
+ * @copy mx.resources.IResourceManager#initializeLocaleChain()
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ public function initializeLocaleChain(compiledLocales:Array):void
+ {
+ localeChain = LocaleSorter.sortLocalesByPreference(
+ compiledLocales, getSystemPreferredLocales(), null, true);
+ }
+
+ /**
+ * @copy mx.resources.IResourceManager#loadResourceModule()
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ COMPILE::LATER
+ public function loadResourceModule(url:String, updateFlag:Boolean = true,
+ applicationDomain:ApplicationDomain = null,
+ securityDomain:SecurityDomain = null):
+ IEventDispatcher
+ {
+ var moduleInfo:IModuleInfo = ModuleManager.getModule(url);
+
+ // Create the per-load IEventDispatcher that we'll return.
+ var resourceEventDispatcher:ResourceEventDispatcher =
+ new ResourceEventDispatcher(moduleInfo);
+
+ // Set up a handler for the "ready" event from the module.
+ // We use a local Function rather than a method
+ // so that it can access the 'update' argument.
+ var readyHandler:Function = function(event:ModuleEvent):void
+ {
+ //trace("readyHandler");
+
+ var resourceModule:* = // IResourceModule
+ event.module.factory.create();
+
+ //dumpResourceModule(resourceModule);
+
+ resourceModules[event.module.url].resourceModule = resourceModule;
+
+ if (updateFlag)
+ update();
+ }
+ moduleInfo.addEventListener(ModuleEvent.READY, readyHandler,
+ false, 0, true);
+
+ // Set up a handler for the "error" event from the module.
+ // We use a local Function rather than a method
+ // for symmetry with the readyHandler.
+ var errorHandler:Function = function(event:ModuleEvent):void
+ {
+ var message:String = "Unable to load resource module from " + url;
+
+ if (resourceEventDispatcher.willTrigger(ResourceEvent.ERROR))
+ {
+ var resourceEvent:ResourceEvent = new ResourceEvent(
+ ResourceEvent.ERROR, event.bubbles, event.cancelable);
+ resourceEvent.bytesLoaded = 0;
+ resourceEvent.bytesTotal = 0;
+ resourceEvent.errorText = message;
+ resourceEventDispatcher.dispatchEvent(resourceEvent);
+ }
+ else
+ {
+ throw new Error(message);
+ }
+ }
+ moduleInfo.addEventListener(ModuleEvent.ERROR, errorHandler,
+ false, 0, true);
+
+ resourceModules[url] =
+ new ResourceModuleInfo(moduleInfo, readyHandler, errorHandler);
+
+ // This Timer gives the loadResourceModules() caller a chance
+ // to add event listeners to the return value, before the module
+ // is loaded.
+ // We use a local Function for the timerHandler rather than a method
+ // so that it can access the 'moduleInfo' local var.
+ var timer:Timer = new Timer(0);
+ var timerHandler:Function = function(event:TimerEvent):void
+ {
+ timer.removeEventListener(TimerEvent.TIMER, timerHandler);
+ timer.stop();
+
+ //trace("loading");
+
+ // Start loading the module.
+ moduleInfo.load(applicationDomain, securityDomain);
+ }
+ timer.addEventListener(TimerEvent.TIMER, timerHandler,
+ false, 0, true);
+ timer.start();
+
+ return resourceEventDispatcher;
+ }
+
+ /**
+ * @copy mx.resources.IResourceManager#unloadResourceModule()
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ COMPILE::LATER
+ public function unloadResourceModule(url:String, update:Boolean = true):void
+ {
+ // Get the resource module info.
+ var rmi:ResourceModuleInfo = resourceModules[url];
+ if (!rmi)
+ return;
+
+ if (rmi.resourceModule)
+ {
+ // Get the bundles in this module.
+ var bundles:Array = rmi.resourceModule.resourceBundles;
+ if (bundles)
+ {
+ var n:int = bundles.length;
+ for (var i:int = 0; i < n; i++)
+ {
+ // Remove each bundle.
+ var locale:String = bundles[i].locale;
+ var bundleName:String = bundles[i].bundleName;
+ removeResourceBundle(locale, bundleName);
+ }
+ }
+ }
+
+ // Remove all links to the module.
+ resourceModules[url] = null;
+ delete resourceModules[url];
+
+ // Unload the module.
+ rmi.moduleInfo.unload();
+
+ // Update if necessary.
+ if (update)
+ this.update();
+ }
+
+ /**
+ * @copy mx.resources.IResourceManager#addResourceBundle()
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ public function addResourceBundle(resourceBundle:IResourceBundle,
+ useWeakReference:Boolean = false):void
+ {
+ var locale:String = resourceBundle.locale;
+ var bundleName:String = resourceBundle.bundleName;
+
+ if (!localeMap[locale])
+ localeMap[locale] = {};
+
+ COMPILE::LATER
+ {
+ if (useWeakReference)
+ {
+ if (!bundleDictionary)
+ {
+ bundleDictionary = new Dictionary(true);
+ }
+
+ bundleDictionary[resourceBundle] = locale + bundleName;
+ localeMap[locale][bundleName] = bundleDictionary;
+ }
+ }
+ //else
+ //{
+ localeMap[locale][bundleName] = resourceBundle;
+ //}
+ }
+
+ /**
+ * @copy mx.resources.IResourceManager#getResourceBundle()
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ public function getResourceBundle(locale:String,
+ bundleName:String):IResourceBundle
+ {
+ return getResourceBundleInternal(locale, bundleName, false);
+ }
+
+ /**
+ * @private
+ *
+ * @param ignoreWeakReferenceBundles if true, do not search weak
+ * reference bundles.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ private function getResourceBundleInternal(locale:String,
+ bundleName:String,
+ ignoreWeakReferenceBundles:Boolean):IResourceBundle
+ {
+ var bundleMap:Object = localeMap[locale];
+ if (!bundleMap)
+ return null;
+
+ var bundle:IResourceBundle = null;
+ var bundleObject:Object = bundleMap[bundleName];
+ COMPILE::LATER
+ {
+ if (bundleObject is Dictionary)
+ {
+ if (ignoreWeakReferenceBundles)
+ return null;
+
+ var localeBundleNameString:String = locale + bundleName;
+ for (var obj:Object in bundleObject)
+ {
+ if (bundleObject[obj] == localeBundleNameString)
+ {
+ if (obj is ResourceBundleProxy)
+ bundle = loadResourceBundleProxy(ResourceBundleProxy(obj));
+ else
+ bundle = obj as IResourceBundle;
+ break;
+ }
+ }
+ }
+ }
+ /* else */if (bundleObject is ResourceBundleProxy)
+ {
+ bundle = loadResourceBundleProxy(ResourceBundleProxy(bundleObject));
+ }
+ else
+ {
+ bundle = bundleObject as IResourceBundle;
+ }
+
+ return bundle;
+ }
+
+ private function loadResourceBundleProxy(proxy:ResourceBundleProxy):ResourceBundle {
+ var proxyClass:Class = proxy.bundleClass;
+ var resourceBundle:ResourceBundle = ResourceBundle(new proxyClass());
+ resourceBundle._locale = proxy.locale;
+ resourceBundle._bundleName = proxy.bundleName;
+
+ addResourceBundle(resourceBundle, proxy.useWeakReference);
+
+ return resourceBundle;
+ }
+
+ /**
+ * @copy mx.resources.IResourceManager#removeResourceBundle()
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ public function removeResourceBundle(locale:String, bundleName:String):void
+ {
+ // Remove the specified bundle.
+ delete localeMap[locale][bundleName];
+
+ // If that leaves a locale node with no bundles,
+ // delete the locale node.
+ if (getBundleNamesForLocale(locale).length == 0)
+ delete localeMap[locale];
+ }
+
+ /**
+ * @copy mx.resources.IResourceManager#removeResourceBundlesForLocale()
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ public function removeResourceBundlesForLocale(locale:String):void
+ {
+ delete localeMap[locale];
+ }
+
+ /**
+ * @copy mx.resources.IResourceManager#update()
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ public function update():void
+ {
+ dispatchEvent(new Event(Event.CHANGE));
+ }
+
+ /**
+ * @copy mx.resources.IResourceManager#getLocales()
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ public function getLocales():Array /* of String */
+ {
+ var locales:Array = [];
+ for (var p:String in localeMap)
+ {
+ locales.push(p);
+ }
+ return locales;
+ }
+
+ /**
+ * @copy mx.resources.IResourceManager#getPreferredLocaleChain()
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ public function getPreferredLocaleChain():Array /* of String */
+ {
+ return LocaleSorter.sortLocalesByPreference(
+ getLocales(), getSystemPreferredLocales(), null, true);
+ }
+
+ /**
+ * @copy mx.resources.IResourceManager#getBundleNamesForLocale()
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ public function getBundleNamesForLocale(locale:String):Array /* of String */
+ {
+ var bundleNames:Array = [];
+ for (var p:String in localeMap[locale])
+ {
+ bundleNames.push(p);
+ }
+ return bundleNames;
+ }
+
+ /**
+ * @copy mx.resources.findResourceBundleWithResource
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ public function findResourceBundleWithResource(
+ bundleName:String, resourceName:String):IResourceBundle
+ {
+ if (!_localeChain)
+ return null;
+
+ var n:int = _localeChain.length;
+ for (var i:int = 0; i < n; i++)
+ {
+ var locale:String = localeChain[i];
+
+ var bundleMap:Object = localeMap[locale];
+ if (!bundleMap)
+ continue;
+
+ var bundleObject:Object = bundleMap[bundleName];
+ if (!bundleObject)
+ continue;
+
+ var bundle:IResourceBundle = null;
+
+ COMPILE::LATER
+ {
+ if (bundleObject is Dictionary)
+ {
+ var localeBundleNameString:String = locale + bundleName;
+ for (var obj:Object in bundleObject)
+ {
+ if (bundleObject[obj] == localeBundleNameString)
+ {
+ if (obj is ResourceBundleProxy)
+ bundle = loadResourceBundleProxy(ResourceBundleProxy(obj));
+ else
+ bundle = obj as IResourceBundle;
+ break;
+ }
+ }
+ }
+ }
+ /* else*/ if (bundleObject is ResourceBundleProxy)
+ {
+ bundle = loadResourceBundleProxy(ResourceBundleProxy(bundleObject));
+ }
+ else
+ {
+ bundle = bundleObject as IResourceBundle;
+ }
+
+ if (bundle && resourceName in bundle.content)
+ return bundle;
+ }
+
+ return null;
+ }
+
+ [Bindable("change")]
+
+ /**
+ * @copy mx.resources.IResourceManager#getObject()
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ public function getObject(bundleName:String, resourceName:String,
+ locale:String = null):*
+ {
+ var resourceBundle:IResourceBundle =
+ findBundle(bundleName, resourceName, locale);
+ if (!resourceBundle)
+ return undefined;
+
+ return resourceBundle.content[resourceName];
+ }
+
+ [Bindable("change")]
+
+ /**
+ * @copy mx.resources.IResourceManager#getString()
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ public function getString(bundleName:String, resourceName:String,
+ parameters:Array = null,
+ locale:String = null):String
+ {
+ var resourceBundle:IResourceBundle =
+ findBundle(bundleName, resourceName, locale);
+ if (!resourceBundle)
+ return null;
+
+ if(!(resourceName in resourceBundle.content))
+ return null;
+
+ var value:String = String(resourceBundle.content[resourceName]);
+
+ if (parameters)
+ value = StringUtil.substitute(value, parameters);
+
+ return value;
+ }
+
+ [Bindable("change")]
+
+ /**
+ * @copy mx.resources.IResourceManager#getStringArray()
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ public function getStringArray(bundleName:String,
+ resourceName:String,
+ locale:String = null):Array /* of String */
+ {
+ var resourceBundle:IResourceBundle =
+ findBundle(bundleName, resourceName, locale);
+ if (!resourceBundle)
+ return null;
+
+ var value:* = resourceBundle.content[resourceName];
+
+ var array:Array = String(value).split(",");
+
+ var n:int = array.length;
+ for (var i:int = 0; i < n; i++)
+ {
+ array[i] = StringUtil.trim(array[i]);
+ }
+
+ return array;
+ }
+
+ [Bindable("change")]
+
+ /**
+ * @copy mx.resources.IResourceManager#getNumber()
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ public function getNumber(bundleName:String, resourceName:String,
+ locale:String = null):Number
+ {
+ var resourceBundle:IResourceBundle =
+ findBundle(bundleName, resourceName, locale);
+ if (!resourceBundle)
+ return NaN;
+
+ var value:* = resourceBundle.content[resourceName];
+
+ return Number(value);
+ }
+
+ [Bindable("change")]
+
+ /**
+ * @copy mx.resources.IResourceManager#getInt()
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ public function getInt(bundleName:String, resourceName:String,
+ locale:String = null):int
+ {
+ var resourceBundle:IResourceBundle =
+ findBundle(bundleName, resourceName, locale);
+ if (!resourceBundle)
+ return 0;
+
+ var value:* = resourceBundle.content[resourceName];
+
+ return int(value);
+ }
+
+ [Bindable("change")]
+
+ /**
+ * @copy mx.resources.IResourceManager#getUint()
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ public function getUint(bundleName:String, resourceName:String,
+ locale:String = null):uint
+ {
+ var resourceBundle:IResourceBundle =
+ findBundle(bundleName, resourceName, locale);
+ if (!resourceBundle)
+ return 0;
+
+ var value:* = resourceBundle.content[resourceName];
+
+ return uint(value);
+ }
+
+ [Bindable("change")]
+
+ /**
+ * @copy mx.resources.IResourceManager#getBoolean()
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ public function getBoolean(bundleName:String, resourceName:String,
+ locale:String = null):Boolean
+ {
+ var resourceBundle:IResourceBundle =
+ findBundle(bundleName, resourceName, locale);
+ if (!resourceBundle)
+ return false;
+
+ var value:* = resourceBundle.content[resourceName];
+
+ return String(value).toLowerCase() == "true";
+ }
+
+ [Bindable("change")]
+
+ /**
+ * @copy mx.resources.IResourceManager#getClass()
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ public function getClass(bundleName:String, resourceName:String,
+ locale:String = null):Class
+ {
+ var resourceBundle:IResourceBundle =
+ findBundle(bundleName, resourceName, locale);
+ if (!resourceBundle)
+ return null;
+
+ var value:* = resourceBundle.content[resourceName];
+
+ return value as Class;
+ }
+
+ /**
+ * @private.
+ */
+ private function findBundle(bundleName:String, resourceName:String,
+ locale:String):IResourceBundle
+ {
+ supportNonFrameworkApps();
+
+ return locale != null ?
+ getResourceBundle(locale, bundleName) :
+ findResourceBundleWithResource(bundleName, resourceName);
+
+ }
+
+ /**
+ * @private.
+ */
+ private function supportNonFrameworkApps():void
+ {
+ if (initializedForNonFrameworkApp)
+ return;
+ initializedForNonFrameworkApp = true;
+
+ if (getLocales().length > 0)
+ return;
+
- COMPILE::AS3
++ COMPILE::SWF
+ {
+ var applicationDomain:DefinitionManager =
+ new DefinitionManager(ApplicationDomain.currentDomain);
+ }
+ COMPILE::JS
+ {
+ var applicationDomain:DefinitionManager =
+ new DefinitionManager();
+ }
+
+ if (!applicationDomain.hasDefinition("_CompiledResourceBundleInfo"))
+ return;
+ var c:Class = Class(applicationDomain.getDefinition(
+ "_CompiledResourceBundleInfo"));
+
+ var locales:Array /* of String */ = c["compiledLocales"];
+ var bundleNames:Array /* of String */ = c["compiledResourceBundleNames"];
+
+ installCompiledResourceBundles(
+ applicationDomain, locales, bundleNames);
+
+ localeChain = locales;
+ }
+
+ /**
+ * @private
+ */
+ private function getSystemPreferredLocales():Array /* of String */
+ {
+ return I18NManager.languages;
+ }
+
+ /**
+ * @private.
+ */
+ private function dumpResourceModule(resourceModule:*):void
+ {
+ for each (var bundle:ResourceBundle in resourceModule.resourceBundles)
+ {
+ trace(bundle.locale, bundle.bundleName);
+ for (var p:String in bundle.content)
+ {
+ //trace(p, bundle.getObject(p));
+ }
+ }
+ }
+
+ /**
+ * @private
+ */
+ private function enterFrameHandler():void
+ {
+ if (SystemManagerGlobals.topLevelSystemManagers.length)
+ {
+ if (SystemManagerGlobals.topLevelSystemManagers[0].currentFrame == 2)
+ {
+ inFrame1 = false;
+ }
+ else
+ {
+ var topSM:UIBase = SystemManagerGlobals.topLevelSystemManagers[0] as UIBase;
+ if (topSM.getBeadByType(CallLaterBead) == null)
+ topSM.addBead(new CallLaterBead());
+ var clb:CallLaterBead = topSM.getBeadByType(CallLaterBead) as CallLaterBead;
+ clb.callLater(enterFrameHandler, null, this);
+ return;
+ }
+ }
+
+ var info:Object = SystemManagerGlobals.info;
+ if (info)
+ processInfo(info, false);
+ }
+}
+
+}
+
+COMPILE::LATER
+{
+import flash.events.EventDispatcher;
+import mx.events.ModuleEvent;
+import mx.events.ResourceEvent;
+import mx.modules.IModuleInfo;
+import mx.resources.IResourceModule;
+}
+import mx.resources.IResourceBundle;
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Helper class: ResourceModuleInfo
+//
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * @private
+ */
+COMPILE::LATER
+class ResourceModuleInfo
+{
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ public function ResourceModuleInfo(moduleInfo:IModuleInfo,
+ readyHandler:Function,
+ errorHandler:Function)
+ {
+ super();
+
+ this.moduleInfo = moduleInfo;
+ this.readyHandler = readyHandler;
+ this.errorHandler = errorHandler;
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Properties
+ //
+ //--------------------------------------------------------------------------
+
+ //----------------------------------
+ // errorHandler
+ //----------------------------------
+
+ /**
+ * @private
+ */
+ public var errorHandler:Function;
+
+ //----------------------------------
+ // moduleInfo
+ //----------------------------------
+
+ /**
+ * @private
+ */
+ public var moduleInfo:IModuleInfo
+
+ //----------------------------------
+ // readyHandler
+ //----------------------------------
+
+ /**
+ * @private
+ */
+ public var readyHandler:Function;
+
+ //----------------------------------
+ // resourceModule
+ //----------------------------------
+
+ /**
+ * @private
+ */
+ public var resourceModule:IResourceModule;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Helper class: ResourceEventDispatcher
+//
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * @private
+ */
+COMPILE::LATER
+class ResourceEventDispatcher extends EventDispatcher
+{
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ public function ResourceEventDispatcher(moduleInfo:IModuleInfo)
+ {
+ super();
+
+ moduleInfo.addEventListener(
+ ModuleEvent.ERROR, moduleInfo_errorHandler, false, 0, true);
+
+ moduleInfo.addEventListener(
+ ModuleEvent.PROGRESS, moduleInfo_progressHandler, false, 0, true);
+
+ moduleInfo.addEventListener(
+ ModuleEvent.READY, moduleInfo_readyHandler, false, 0, true);
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Event handlers
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ private function moduleInfo_errorHandler(event:ModuleEvent):void
+ {
+ var resourceEvent:ResourceEvent = new ResourceEvent(
+ ResourceEvent.ERROR, event.bubbles, event.cancelable);
+ resourceEvent.bytesLoaded = event.bytesLoaded;
+ resourceEvent.bytesTotal = event.bytesTotal;
+ resourceEvent.errorText = event.errorText;
+ dispatchEvent(resourceEvent);
+ }
+
+ /**
+ * @private
+ */
+ private function moduleInfo_progressHandler(event:ModuleEvent):void
+ {
+ var resourceEvent:ResourceEvent = new ResourceEvent(
+ ResourceEvent.PROGRESS, event.bubbles, event.cancelable);
+ resourceEvent.bytesLoaded = event.bytesLoaded;
+ resourceEvent.bytesTotal = event.bytesTotal;
+ dispatchEvent(resourceEvent);
+ }
+
+ /**
+ * @private
+ */
+ private function moduleInfo_readyHandler(event:ModuleEvent):void
+ {
+ var resourceEvent:ResourceEvent =
+ new ResourceEvent(ResourceEvent.COMPLETE);
+ dispatchEvent(resourceEvent);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Helper class: ResourceBundleProxy
+//
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * @private
+ */
+class ResourceBundleProxy implements IResourceBundle
+{
+ public var bundleClass:Class;
+ public var useWeakReference:Boolean;
+
+ private var _bundleName:String;
+ private var _locale:String;
+
+ public function ResourceBundleProxy()
+ {
+ }
+
+ public function get bundleName():String {
+ return _bundleName;
+ }
+
+ public function set bundleName(value:String):void {
+ _bundleName = value;
+ }
+
+ public function get content():Object {
+ return null;
+ }
+
+ public function get locale():String {
+ return _locale;
+ }
+
+ public function set locale(value:String):void {
+ _locale = value;
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/77148f4a/frameworks/projects/MX/src/main/flex/mx/states/AddChild.as
----------------------------------------------------------------------
diff --cc frameworks/projects/MX/src/main/flex/mx/states/AddChild.as
index 68b17a6,0000000..07c9418
mode 100644,000000..100644
--- a/frameworks/projects/MX/src/main/flex/mx/states/AddChild.as
+++ b/frameworks/projects/MX/src/main/flex/mx/states/AddChild.as
@@@ -1,536 -1,0 +1,536 @@@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package mx.states
+{
+
- COMPILE::AS3
++COMPILE::SWF
+{
+ import flash.display.DisplayObject;
+ import flash.display.DisplayObjectContainer;
+}
+COMPILE::JS
+{
+ import flex.display.DisplayObject;
+ import flex.display.DisplayObjectContainer;
+}
+import mx.core.ContainerCreationPolicy;
+import mx.core.IDeferredInstance;
+import mx.core.mx_internal;
+import mx.core.UIComponent;
+import mx.resources.IResourceManager;
+import mx.resources.ResourceManager;
+
+use namespace mx_internal;
+
+[DefaultProperty("targetFactory")]
+
+[ResourceBundle("states")]
+
+/**
+ * The AddChild class adds a child display object, such as a component,
+ * to a container as part of a view state.
+ * You use this class in the <code>overrides</code> property of the State class.
+ * Use the <code>creationPolicy</code> property to specify to create the child
+ * at application startup or when you change to a view state.
+ *
+ * <p>The child does not dispatch the <code>creationComplete</code> event until
+ * it is added to a container. For example, the following code adds a
+ * Button control as part of a view state change:</p>
+ *
+ * <pre>
+ * <mx:AddChild relativeTo="{v1}">
+ * <mx:Button id="b0" label="New Button"/>
+ * </mx:AddChild> </pre>
+ *
+ * <p>In the previous example, the Button control does not dispatch
+ * the <code>creationComplete</code> event until you change state and the
+ * Button control is added to a container.
+ * If the AddChild class defines both the Button and a container, such as a Canvas container,
+ * then the Button control dispatches the creationComplete event when it is created.
+ * For example, if the <code>creationPolicy</code> property is set to <code>all</code>,
+ * the Button control dispatches the event at application startup.
+ * If the <code>creationPolicy</code> property is set to <code>auto</code>,
+ * the Button control dispatches the event when you change to the view state. </p>
+ *
+ * @mxml
+ *
+ * <p>The <code><mx:AddChild></code> tag
+ * has the following attributes:</p>
+ *
+ * <pre>
+ * <mx:AddChild
+ * <b>Properties</b>
+ * target="null"
+ * targetFactory="null"
+ * creationPolicy="auto"
+ * position="lastChild"
+ * relativeTo="<i>parent of the State object</i>"
+ * />
+ * </pre>
+ *
+ * @see mx.states.State
+ * @see mx.states.RemoveChild
+ * @see mx.states.Transition
+ * @see mx.effects.AddChildAction
+ *
+ * @includeExample examples/StatesExample.mxml
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ public class AddChild extends OverrideBase
+{
+ include "../core/Version.as";
+
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @param relativeTo The component relative to which child is added.
+ *
+ * @param target The child object.
+ * All Flex components are subclasses of the DisplayObject class.
+ *
+ * @param position the location in the display list of the <code>target</code>
+ * relative to the <code>relativeTo</code> component. Must be one of the following:
+ * "firstChild", "lastChild", "before" or "after".
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ public function AddChild(relativeTo:UIComponent = null,
+ target:DisplayObject = null,
+ position:String = "lastChild")
+ {
+ super();
+
+ this.relativeTo = relativeTo;
+ this.target = target;
+ this.position = position;
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Variables
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ mx_internal var added:Boolean = false;
+
+ /**
+ * @private
+ */
+ mx_internal var instanceCreated:Boolean = false;
+
+ /**
+ * @private
+ * Used for accessing localized Error messages.
+ */
+ private var resourceManager:IResourceManager =
+ ResourceManager.getInstance();
+
+ //--------------------------------------------------------------------------
+ //
+ // Properties
+ //
+ //--------------------------------------------------------------------------
+
+ //------------------------------------
+ // creationPolicy
+ //------------------------------------
+
+ /**
+ * @private
+ * Storage for the creationPolicy property.
+ */
+ private var _creationPolicy:String = ContainerCreationPolicy.AUTO;
+
+ [Inspectable(category="General")]
+
+ /**
+ * The creation policy for this child.
+ * This property determines when the <code>targetFactory</code> will create
+ * the instance of the child.
+ * Flex uses this properthy only if you specify a <code>targetFactory</code> property.
+ * The following values are valid:
+ *
+ * <p></p>
+ * <table class="innertable">
+ * <tr><th>Value</th><th>Meaning</th></tr>
+ * <tr><td><code>auto</code></td><td>(default)Create the instance the
+ * first time it is needed.</td></tr>
+ * <tr><td><code>all</code></td><td>Create the instance when the
+ * application started up.</td></tr>
+ * <tr><td><code>none</code></td><td>Do not automatically create the instance.
+ * You must call the <code>createInstance()</code> method to create
+ * the instance.</td></tr>
+ * </table>
+ *
+ * @default "auto"
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ public function get creationPolicy():String
+ {
+ return _creationPolicy;
+ }
+
+ /**
+ * @private
+ */
+ public function set creationPolicy(value:String):void
+ {
+ _creationPolicy = value;
+
+ if (_creationPolicy == ContainerCreationPolicy.ALL)
+ createInstance();
+ }
+
+ //------------------------------------
+ // position
+ //------------------------------------
+
+ [Inspectable(category="General")]
+
+ /**
+ * The position of the child in the display list, relative to the
+ * object specified by the <code>relativeTo</code> property.
+ * Valid values are <code>"before"</code>, <code>"after"</code>,
+ * <code>"firstChild"</code>, and <code>"lastChild"</code>.
+ *
+ * @default "lastChild"
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ public var position:String;
+
+ //------------------------------------
+ // relativeTo
+ //------------------------------------
+
+ [Inspectable(category="General")]
+
+ /**
+ * The object relative to which the child is added. This property is used
+ * in conjunction with the <code>position</code> property.
+ * This property is optional; if
+ * you omit it, Flex uses the immediate parent of the <code>State</code>
+ * object, that is, the component that has the <code>states</code>
+ * property, or <code><mx:states></code>tag that specifies the State
+ * object.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ public var relativeTo:Object;
+
+ //------------------------------------
+ // target
+ //------------------------------------
+
+ /**
+ * @private
+ * Storage for the target property
+ */
+ private var _target:DisplayObject;
+
+ [Inspectable(category="General")]
+
+ /**
+ *
+ * The child to be added.
+ * If you set this property, the child instance is created at app startup.
+ * Setting this property is equivalent to setting a <code>targetFactory</code>
+ * property with a <code>creationPolicy</code> of <code>"all"</code>.
+ *
+ * <p>Do not set this property if you set the <code>targetFactory</code>
+ * property.</p>
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ public function get target():DisplayObject
+ {
+ if (!_target && creationPolicy != ContainerCreationPolicy.NONE)
+ createInstance();
+
+ return _target;
+ }
+
+ /**
+ * @private
+ */
+ public function set target(value:DisplayObject):void
+ {
+ _target = value;
+ }
+
+ //------------------------------------
+ // targetFactory
+ //------------------------------------
+
+ /**
+ * @private
+ * Storage for the targetFactory property.
+ */
+ private var _targetFactory:IDeferredInstance;
+
+ [Inspectable(category="General")]
+
+ /**
+ *
+ * The factory that creates the child. You can specify either of the following items:
+ * <ul>
+ * <li>A factory class that implements the IDeferredInstance
+ * interface and creates the child instance or instances.
+ * </li>
+ * <li>A Flex component, (that is, any class that is a subclass
+ * of the UIComponent class), such as the Button contol.
+ * If you use a Flex component, the Flex compiler automatically
+ * wraps the component in a factory class.
+ * </li>
+ * </ul>
+ *
+ * <p>If you set this property, the child is instantiated at the time
+ * determined by the <code>creationPolicy</code> property.</p>
+ *
+ * <p>Do not set this property if you set the <code>target</code>
+ * property.
+ * This propety is the <code>AddChild</code> class default property.
+ * Setting this property with a <code>creationPolicy</code> of "all"
+ * is equivalent to setting a <code>target</code> property.</p>
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ public function get targetFactory():IDeferredInstance
+ {
+ return _targetFactory;
+ }
+
+ /**
+ * @private
+ */
+ public function set targetFactory(value:IDeferredInstance):void
+ {
+ _targetFactory = value;
+
+ if (creationPolicy == ContainerCreationPolicy.ALL)
+ createInstance();
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Methods
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Creates the child instance from the factory.
+ * You must use this method only if you specify a <code>targetFactory</code>
+ * property and a <code>creationPolicy</code> value of <code>"none"</code>.
+ * Flex automatically calls this method if the <code>creationPolicy</code>
+ * property value is <code>"auto"</code> or <code>"all"</code>.
+ * If you call this method multiple times, the child instance is
+ * created only on the first call.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ public function createInstance():void
+ {
+ if (!instanceCreated && !_target && targetFactory)
+ {
+ instanceCreated = true;
+ var instance:Object = targetFactory.getInstance();
+ if (instance is DisplayObject)
+ _target = DisplayObject(instance);
+ }
+ }
+
+ /**
+ * @inheritDoc
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ override public function initialize():void
+ {
+ if (creationPolicy == ContainerCreationPolicy.AUTO)
+ createInstance();
+ }
+
+ /**
+ * @inheritDoc
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ override public function apply(parent:UIComponent):void
+ {
+ var obj:* = getOverrideContext(relativeTo, parent);
+
+ parentContext = parent;
+ added = false;
+
+ // Early exit if child is null or not a valid container.
+ if (!target || !(obj is DisplayObjectContainer))
+ {
+ if (relativeTo != null && !applied)
+ {
+ // Our destination context is unavailable so we attempt to register
+ // a listener on our parent document to detect when/if it becomes
+ // valid.
+ addContextListener(relativeTo);
+ }
+ applied = true;
+ return;
+ }
+
+ applied = true;
+ relativeTo = obj;
+
+ // Can't reparent. Must remove before adding.
+ if (target.parent)
+ {
+ var message:String = resourceManager.getString(
+ "states", "alreadyParented");
+ throw new Error(message);
+ return;
+ }
+
+ switch (position)
+ {
+ case "before":
+ {
+ obj.parent.addChildAt(target,
+ obj.parent.getChildIndex(obj));
+ break;
+ }
+
+ case "after":
+ {
+ obj.parent.addChildAt(target,
+ obj.parent.getChildIndex(obj) + 1);
+ break;
+ }
+
+ case "firstChild":
+ {
+ obj.addChildAt(target, 0);
+ break;
+ }
+
+ case "lastChild":
+ default:
+ {
+ obj.addChild(target);
+ break;
+ }
+ }
+
+ added = true;
+ }
+
+ /**
+ * @inheritDoc
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ override public function remove(parent:UIComponent):void
+ {
+ var obj:* = getOverrideContext(relativeTo, parent);
+
+ if (!added || !(obj is DisplayObjectContainer))
+ {
+ if (obj == null)
+ {
+ // It seems our override is no longer active, but we were never
+ // able to successfully apply ourselves, so remove our context
+ // listener if applicable.
+ removeContextListener();
+ applied = false;
+ parentContext = null;
+ }
+ return;
+ }
+
+ switch (position)
+ {
+ case "before":
+ case "after":
+ {
+ obj.parent.removeChild(target);
+ break;
+ }
+
+ case "firstChild":
+ case "lastChild":
+ default:
+ {
+ if (obj == target.parent)
+ {
+ obj.removeChild(target);
+ }
+ break;
+ }
+ }
+
+ // Clear our flags and override context.
+ added = false;
+ applied = false;
+ parentContext = null;
+ }
+}
+
+}