////////////////////////////////////////////////////////////////////////////////
//
// 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
{
import flash.display.DisplayObject;
import flash.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 overrides
property of the State class.
* Use the creationPolicy
property to specify to create the child
* at application startup or when you change to a view state.
*
*
The child does not dispatch the creationComplete
event until
* it is added to a container. For example, the following code adds a
* Button control as part of a view state change:
* <mx:AddChild relativeTo="{v1}"> * <mx:Button id="b0" label="New Button"/> * </mx:AddChild>* *
In the previous example, the Button control does not dispatch
* the creationComplete
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 creationPolicy
property is set to all
,
* the Button control dispatches the event at application startup.
* If the creationPolicy
property is set to auto
,
* the Button control dispatches the event when you change to the view state.
The <mx:AddChild>
tag
* has the following attributes:
* <mx:AddChild * Properties * target="null" * targetFactory="null" * creationPolicy="auto" * position="lastChild" * relativeTo="parent of the State object" * /> ** * @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
target
* relative to the relativeTo
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 targetFactory
will create
* the instance of the child.
* Flex uses this properthy only if you specify a targetFactory
property.
* The following values are valid:
*
*
* Value | Meaning |
---|---|
auto | (default)Create the instance the * first time it is needed. |
all | Create the instance when the * application started up. |
none | Do not automatically create the instance.
* You must call the createInstance() method to create
* the instance. |
relativeTo
property.
* Valid values are "before"
, "after"
,
* "firstChild"
, and "lastChild"
.
*
* @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 position
property.
* This property is optional; if
* you omit it, Flex uses the immediate parent of the State
* object, that is, the component that has the states
* property, or <mx:states>
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 targetFactory
* property with a creationPolicy
of "all"
.
*
* Do not set this property if you set the targetFactory
* property.
If you set this property, the child is instantiated at the time
* determined by the creationPolicy
property.
Do not set this property if you set the target
* property.
* This propety is the AddChild
class default property.
* Setting this property with a creationPolicy
of "all"
* is equivalent to setting a target
property.
targetFactory
* property and a creationPolicy
value of "none"
.
* Flex automatically calls this method if the creationPolicy
* property value is "auto"
or "all"
.
* 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;
}
}
}