////////////////////////////////////////////////////////////////////////////////
//
// 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.flash
{
import flash.display.DisplayObject;
import flash.display.DisplayObjectContainer;
import flash.display.InteractiveObject;
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.display.Stage;
import flash.events.Event;
import flash.events.FocusEvent;
import flash.geom.ColorTransform;
import flash.geom.Matrix;
import flash.geom.Matrix3D;
import flash.geom.PerspectiveProjection;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.geom.Vector3D;
import flash.system.ApplicationDomain;
import flash.ui.Keyboard;
import mx.automation.IAutomationObject;
import mx.core.AdvancedLayoutFeatures;
import mx.core.DesignLayer;
import mx.core.IConstraintClient;
import mx.core.IDeferredInstantiationUIComponent;
import mx.core.IFlexDisplayObject;
import mx.core.IFlexModule;
import mx.core.IFlexModuleFactory;
import mx.core.IInvalidating;
import mx.core.ILayoutElement;
import mx.core.IStateClient;
import mx.core.IUIComponent;
import mx.core.IVisualElement;
import mx.core.LayoutElementUIComponentUtils;
import mx.core.LayoutDirection;
import mx.core.UIComponentDescriptor;
import mx.core.mx_internal;
import mx.events.FlexEvent;
import mx.events.MoveEvent;
import mx.events.PropertyChangeEvent;
import mx.events.ResizeEvent;
import mx.events.StateChangeEvent;
import mx.geom.TransformOffsets;
import mx.managers.IFocusManagerComponent;
import mx.managers.ISystemManager;
import mx.managers.IToolTipManagerClient;
import mx.utils.MatrixUtil;
import mx.utils.TransformUtil;
use namespace mx_internal;
//--------------------------------------
// Lifecycle events
//--------------------------------------
/**
* Dispatched when the component is added to a container as a content child
* by using the addChild()
or addChildAt()
method.
* If the component is added to the container as a noncontent child by
* using the rawChildren.addChild()
or
* rawChildren.addChildAt()
method, the event is not dispatched.
*
* @eventType mx.events.FlexEvent.ADD
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
[Event(name="add", type="mx.events.FlexEvent")]
/**
* Dispatched when the component has finished its construction.
* For Flash-based components, this is the same time as the
* initialize
event.
*
* @eventType mx.events.FlexEvent.CREATION_COMPLETE
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
[Event(name="creationComplete", type="mx.events.FlexEvent")]
/**
* Dispatched when an object's state changes from visible to invisible.
*
* @eventType mx.events.FlexEvent.HIDE
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
[Event(name="hide", type="mx.events.FlexEvent")]
/**
* Dispatched when the component has finished its construction
* and has all initialization properties set.
*
* @eventType mx.events.FlexEvent.INITIALIZE
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
[Event(name="initialize", type="mx.events.FlexEvent")]
/**
* Dispatched when the object has moved.
*
*
You can move the component by setting the x
* or y
properties, by calling the move()
* method, by setting one
* of the following properties either on the component or on other
* components such that the LayoutManager needs to change the
* x
or y
properties of the component:
minWidth
minHeight
maxWidth
maxHeight
explicitWidth
explicitHeight
When you call the move()
method, the move
* event is dispatched before the method returns.
* In all other situations, the move
event is not dispatched
* until after the property changes.
preinitialize
event,
* the children, including the internal children, of a component
* have not yet been created.
*
* @eventType mx.events.FlexEvent.PREINITIALIZE
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
[Event(name="preinitialize", type="mx.events.FlexEvent")]
/**
* Dispatched when the component is removed from a container as a content child
* by using the removeChild()
or removeChildAt()
method.
* If the component is removed from the container as a noncontent child by
* using the rawChildren.removeChild()
or
* rawChildren.removeChildAt()
method, the event is not dispatched.
*
* @eventType mx.events.FlexEvent.REMOVE
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
[Event(name="remove", type="mx.events.FlexEvent")]
/**
* Dispatched when the component is resized.
*
* You can resize the component by setting the width
or
* height
property, by calling the setActualSize()
* method, or by setting one of
* the following properties either on the component or on other components
* such that the LayoutManager needs to change the width
or
* height
properties of the component:
minWidth
minHeight
maxWidth
maxHeight
explicitWidth
explicitHeight
The resize
event is not
* dispatched until after the property changes.
In order to be a valid drop target, you must define a handler * for this event. * In the handler, you can change the appearance of the drop target * to provide visual feedback to the user that the component can accept * the drag. * For example, you could draw a border around the drop target, * or give focus to the drop target.
* *If you want to accept the drag, you must call the
* DragManager.acceptDragDrop()
method. If you don't
* call acceptDragDrop()
, you will not get any of the
* other drag events.
The value of the action
property is always
* DragManager.MOVE
, even if you are doing a copy.
* This is because the dragEnter
event occurs before
* the control recognizes that the Control key is pressed to signal a copy.
* The action
property of the event object for the
* dragOver
event does contain a value that signifies the type of
* drag operation.
You may change the type of drag action by calling the
* DragManager.showFeedback()
method.
In the handler, you can change the appearance of the drop target * to provide visual feedback to the user that the component can accept * the drag. * For example, you could draw a border around the drop target, * or give focus to the drop target.
* *You should handle this event to perform additional logic * before allowing the drop, such as dropping data to various locations * in the drop target, reading keyboard input to determine if the * drag-and-drop action is a move or copy of the drag data, or providing * different types of visual feedback based on the type of drag-and-drop * action.
* *You may also change the type of drag action by changing the
* DragManager.showFeedback()
method.
* The default value of the action
property is
* DragManager.MOVE
.
You use this event to restore the drop target to its normal appearance
* if you modified its appearance as part of handling the
* dragEnter
or dragOver
event.
You use this event handler to add the drag data to the drop target.
* *If you call Event.preventDefault()
in the event handler
* for the dragDrop
event for
* a Tree control when dragging data from one Tree control to another,
* it prevents the drop.
You can use this event to perform any final cleanup * of the drag-and-drop operation. * For example, if you drag a List control item from one list to another, * you can delete the List control item from the source if you no longer * need it.
* *If you call Event.preventDefault()
in the event handler
* for the dragComplete
event for
* a Tree control when dragging data from one Tree control to another,
* it prevents the drop.
currentState
property changes,
* but before the view state changes.
*
* @eventType mx.events.StateChangeEvent.CURRENT_STATE_CHANGING
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
[Event(name="currentStateChanging", type="mx.events.StateChangeEvent")]
/**
* Dispatched after the view state has changed.
*
* @eventType mx.events.StateChangeEvent.CURRENT_STATE_CHANGE
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
[Event(name="currentStateChange", type="mx.events.StateChangeEvent")]
//--------------------------------------
// Tooltip events
//--------------------------------------
/**
* Dispatched by the component when it is time to create a ToolTip.
*
* If you create your own IToolTip object and place a reference
* to it in the toolTip
property of the event object
* that is passed to your toolTipCreate
handler,
* the ToolTipManager displays your custom ToolTip.
* Otherwise, the ToolTipManager creates an instance of
* ToolTipManager.toolTipClass
to display.
The sequence of ToolTip events is toolTipStart
,
* toolTipCreate
, toolTipShow
,
* toolTipShown
, toolTipHide
,
* and toolTipEnd
.
If you specify an effect using the
* ToolTipManager.hideEffect
property,
* this event is dispatched after the effect stops playing.
The sequence of ToolTip events is toolTipStart
,
* toolTipCreate
, toolTipShow
,
* toolTipShown
, toolTipHide
,
* and toolTipEnd
.
If you specify an effect using the
* ToolTipManager.hideEffect
property,
* this event is dispatched before the effect starts playing.
The sequence of ToolTip events is toolTipStart
,
* toolTipCreate
, toolTipShow
,
* toolTipShown
, toolTipHide
,
* and toolTipEnd
.
If you specify an effect using the
* ToolTipManager.showEffect
property,
* this event is dispatched before the effect starts playing.
* You can use this event to modify the ToolTip before it appears.
The sequence of ToolTip events is toolTipStart
,
* toolTipCreate
, toolTipShow
,
* toolTipShown
, toolTipHide
,
* and toolTipEnd
.
If you specify an effect using the
* ToolTipManager.showEffect
property,
* this event is dispatched after the effect stops playing.
The sequence of ToolTip events is toolTipStart
,
* toolTipCreate
, toolTipShow
,
* toolTipShown
, toolTipHide
,
* and toolTipEnd
.
toolTip
property is set,
* as soon as the user moves the mouse over it.
*
* The sequence of ToolTip events is toolTipStart
,
* toolTipCreate
, toolTipShow
,
* toolTipShown
, toolTipHide
,
* and toolTipEnd
.
The following procedure describes the basic process for creating * a Flex component in Flash Professional:
* *library-path
when you compile
* your Flex application.For more information, see the documentation that ships with the * Flex/Flash Integration Kit at * http://www.adobe.com/go/flex3_cs3_swfkit.
* * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public dynamic class UIMovieClip extends MovieClip implements IDeferredInstantiationUIComponent, IToolTipManagerClient, IStateClient, IFocusManagerComponent, IConstraintClient, IAutomationObject, IVisualElement, ILayoutElement, IFlexModule { //-------------------------------------------------------------------------- // // Constructor // //-------------------------------------------------------------------------- /** * Constructor. * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function UIMovieClip() { super(); // Add a focus in event handler so we can catch mouse focus within our // content. addEventListener(FocusEvent.FOCUS_IN, focusInHandler, false, 0, true); // Add a creationComplete handler so we can attach an event handler // to the stage addEventListener(FlexEvent.CREATION_COMPLETE, creationCompleteHandler); // we want to set currentState initially by checking the currentLabel, but we // defer this so that if curentState is set explicitely, // we do a goToAndStop() instead of short-circuiting the currentState // setter at "if (value == _currentState)" addEventListener(Event.ENTER_FRAME, setUpFirstCurrentState); } //-------------------------------------------------------------------------- // // Internal variables // //-------------------------------------------------------------------------- /** * @copy mx.core.UIComponent#initialized * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ protected var initialized:Boolean = false; private var validateMeasuredSizeFlag:Boolean = true; private var _parent:DisplayObjectContainer; private var stateMap:Object; // Focus vars private var focusableObjects:Array = []; private var reverseDirectionFocus:Boolean = false; private var focusListenersAdded:Boolean = false; // Transition playhead vars private var transitionStartFrame:Number; private var transitionEndFrame:Number; private var transitionDirection:Number = 0; private var transitionEndState:String; // Location change detection vars private var oldX:Number; private var oldY:Number; private var oldWidth:Number; private var oldHeight:Number; private var explicitSizeChanged:Boolean = false; private var explicitTabEnabledChanged:Boolean = false; //-------------------------------------------------------------------------- // // Public variables // //-------------------------------------------------------------------------- //---------------------------------- // alpha //---------------------------------- /** * @private * Storage for the alpha property. */ private var _alpha:Number = 1.0; /** * @private */ override public function get alpha():Number { // Here we roundtrip alpha in the same manner as the // player (purposely introducing a rounding error). return int(_alpha * 256.0) / 256.0; } /** * @private */ override public function set alpha(value:Number):void { if (_alpha != value) { _alpha = value; if (designLayer) value = value * designLayer.effectiveAlpha; super.alpha = value; } } //---------------------------------- // autoUpdateMeasuredSize //---------------------------------- /** * @private */ private var _autoUpdateMeasuredSize:Boolean = false; [Inspectable(category="General")] /** * Whether we should actively watch changes to the size of the flash object. * If this is set totrue
, then every frame, the size of the flash
* object will be determined. If the size has changed, then the flash object
* will scale appropriately to fit its explicit bounds (or it will resize and
* notify its parent if there is no explicit sizing).
*
* Note: Setting this property to true
may be expensive because
* we now are asking the flash object its current size every single frame.
currentState
property depends on this flash label.
* If this is set to true
, then every frame, the label of the flash
* obejct will be quieried. If the label has changed, that will become the new
* currentState
for the Flex object.
*
* Note: Setting this property to true
may be expensive because
* we now are asking the flash object for is current label every single frame.
Setting this property directly or calling move()
* will have no effect -- or only a temporary effect -- if the
* component is parented by a layout container such as HBox, Grid,
* or Form, because the layout calculations of those containers
* set the x
position to the results of the calculation.
* However, the x
property must almost always be set
* when the parent is a Canvas or other absolute-positioning
* container because the default value is 0.
Setting this property directly or calling move()
* will have no effect -- or only a temporary effect -- if the
* component is parented by a layout container such as HBox, Grid,
* or Form, because the layout calculations of those containers
* set the x
position to the results of the calculation.
* However, the x
property must almost always be set
* when the parent is a Canvas or other absolute-positioning
* container because the default value is 0.
The bounding box is an object that is used by Flex to determine * the size of the component. The actual content can be larger or * smaller than the bounding box, but Flex uses the size of the * bounding box when laying out the component. This object is optional. * If omitted, the actual content size of the component is used instead.
* * @default "boundingBox" * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public var boundingBoxName:String = "boundingBox"; //---------------------------------- // Layout Constraints //---------------------------------- private var _baseline:*; [Inspectable] [Bindable] /** * The vertical distance in pixels from the top edge of the content area * to the component's baseline position. * If this property is set, the baseline of the component is anchored * to the top edge of its content area; * when its container is resized, the two edges maintain their separation. * *This property only has an effect when used on a component in a Canvas container,
* or when used on a component in a Panel or Application container
* that has the layout property set to absolute
.
The default value is undefined
, which means it is not set.
This property only has an effect when used on a component in a Canvas container,
* or when used on a component in a Panel or Application container
* that has the layout property set to absolute
.
The default value is undefined
, which means it is not set.
This property only has an effect when used on a component in a Canvas container,
* or when used on a component in a Panel or Application container
* that has the layout property set to absolute
.
The default value is undefined
, which means it is not set.
This property only has an effect when used on a component in a Canvas container,
* or when used on a component in a Panel or Application container
* that has the layout property set to absolute
.
The default value is undefined
, which means it is not set.
This property only has an effect when used on a component in a Canvas container,
* or when used on a component in a Panel or Application container
* that has the layout property set to absolute
.
The default value is undefined
, which means it is not set.
This property only has an effect when used on a component in a Canvas container,
* or when used on a component in a Panel or Application container
* that has the layout property set to absolute
.
The default value is undefined
, which means it is not set.
This property only has an effect when used on a component in a Canvas container,
* or when used on a component in a Panel or Application container
* that has the layout property set to absolute
.
The default value is undefined
, which means it is not set.
cachePolicy
is UIComponentCachePolicy.AUTO
,
* then cacheHeuristic
* is used to control the object's cacheAsBitmap
property.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function set cacheHeuristic(value:Boolean):void
{
// ignored
}
//----------------------------------
// cachePolicy
//----------------------------------
/**
* Specifies the bitmap caching policy for this object.
* Possible values in MXML are "on"
,
* "off"
and
* "auto"
(default).
*
* Possible values in ActionScript are UIComponentCachePolicy.ON
,
* UIComponentCachePolicy.OFF
and
* UIComponentCachePolicy.AUTO
(default).
UIComponentCachePolicy.ON
means that
* the object is always cached as a bitmap.UIComponentCachePolicy.OFF
means that
* the object is never cached as a bitmap.UIComponentCachePolicy.AUTO
means that
* the framework uses heuristics to decide whether the object should
* be cached as a bitmap.createComponentFromDescriptor()
method to create this
* UIComponent instance. If this UIComponent instance
* was not created from a descriptor, this property is null.
*
* @see mx.core.UIComponentDescriptor
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get descriptor():UIComponentDescriptor
{
return _descriptor;
}
/**
* @private
*/
public function set descriptor(value:UIComponentDescriptor):void
{
_descriptor = value;
}
//----------------------------------
// id
//----------------------------------
private var _id:String;
/**
* ID of the component. This value becomes the instance name of the object
* and should not contain any white space or special characters. Each component
* throughout an application should have a unique id.
*
* If your application is going to be tested by third party tools, give each component * a meaningful id. Testing tools use ids to represent the control in their scripts and * having a meaningful name can make scripts more readable. For example, set the * value of a button to submit_button rather than b1 or button1.
* * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get id():String { return _id; } /** * @private */ public function set id(value:String):void { _id = value; } //-------------------------------------------------------------------------- // // IDeferredInstantiationUIComponent methods // //-------------------------------------------------------------------------- /** * Creates anid
reference to this IUIComponent object
* on its parent document object.
* This function can create multidimensional references
* such as b[2][4] for objects inside one or more repeaters.
* If the indices are null, it creates a simple non-Array reference.
*
* @param parentDocument The parent of this IUIComponent object.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function createReferenceOnParentDocument(
parentDocument:IFlexDisplayObject):void
{
if (id && id != "")
{
parentDocument[id] = this;
}
}
/**
* Deletes the id
reference to this IUIComponent object
* on its parent document object.
* This function can delete from multidimensional references
* such as b[2][4] for objects inside one or more Repeaters.
* If the indices are null, it deletes the simple non-Array reference.
*
* @param parentDocument The parent of this IUIComponent object.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function deleteReferenceOnParentDocument(
parentDocument:IFlexDisplayObject):void
{
if (id && id != "")
{
parentDocument[id] = null;
}
}
/**
* Executes the data bindings into this UIComponent object.
*
* @param recurse Recursively execute bindings for children of this component.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function executeBindings(recurse:Boolean = false):void
{
var bindingsHost:Object = descriptor && descriptor.document ? descriptor.document : parentDocument;
var mgr:* = ApplicationDomain.currentDomain.getDefinition("mx.binding.BindingManager");
if (mgr != null)
mgr.executeBindings(bindingsHost, id, this);
}
/**
* For each effect event, register the EffectManager
* as one of the event listeners.
*
* @param effects An Array of strings of effect names.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function registerEffects(effects:Array /* of String*/):void
{
// ignored
}
//--------------------------------------------------------------------------
//
// IUIComponent properties
//
//--------------------------------------------------------------------------
//----------------------------------
// baselinePosition
//----------------------------------
/**
* The y-coordinate of the baseline
* of the first line of text of the component.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get baselinePosition():Number
{
return 0;
}
//----------------------------------
// document
//----------------------------------
mx_internal var _document:Object;
/**
* @copy mx.core.IUIComponent#document
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get document():Object
{
return _document;
}
/**
* @private
*/
public function set document(value:Object):void
{
_document = value;
}
//----------------------------------
// explicitHeight
//----------------------------------
private var _explicitHeight:Number;
/**
* The explicitly specified height for the component,
* in pixels, as the component's coordinates.
* If no height is explicitly specified, the value is NaN
.
*
* @see mx.core.UIComponent#explicitHeight
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get explicitHeight():Number
{
return _explicitHeight;
}
/**
* @private
*/
public function set explicitHeight(value:Number):void
{
_explicitHeight = value;
explicitSizeChanged = true;
invalidateParentSizeAndDisplayList();
addEventListener(Event.ENTER_FRAME, enterFrameHandler, false, 0, true);
}
//----------------------------------
// explicitMaxHeight
//----------------------------------
private var _explicitMaxHeight:Number;
/**
* Number that specifies the maximum height of the component,
* in pixels, as the component's coordinates.
*
* @see mx.core.UIComponent#explicitMaxHeight
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get explicitMaxHeight():Number
{
return _explicitMaxHeight;
}
public function set explicitMaxHeight(value:Number):void
{
_explicitMaxHeight = value;
invalidateParentSizeAndDisplayList();
}
//----------------------------------
// explicitMaxWidth
//----------------------------------
private var _explicitMaxWidth:Number;
/**
* Number that specifies the maximum width of the component,
* in pixels, as the component's coordinates.
*
* @see mx.core.UIComponent#explicitMaxWidth
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get explicitMaxWidth():Number
{
return _explicitMaxWidth;
}
public function set explicitMaxWidth(value:Number):void
{
_explicitMaxWidth = value;
invalidateParentSizeAndDisplayList();
}
//----------------------------------
// explicitMinHeight
//----------------------------------
private var _explicitMinHeight:Number;
/**
* Number that specifies the minimum height of the component,
* in pixels, as the component's coordinates.
*
* @see mx.core.UIComponent#explicitMinHeight
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get explicitMinHeight():Number
{
return _explicitMinHeight;
}
public function set explicitMinHeight(value:Number):void
{
_explicitMinHeight = value;
invalidateParentSizeAndDisplayList();
}
//----------------------------------
// explicitMinWidth
//----------------------------------
private var _explicitMinWidth:Number;
/**
* Number that specifies the minimum width of the component,
* in pixels, as the component's coordinates.
*
* @see mx.core.UIComponent#explicitMinWidth
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get explicitMinWidth():Number
{
return _explicitMinWidth;
}
public function set explicitMinWidth(value:Number):void
{
_explicitMinWidth = value;
invalidateParentSizeAndDisplayList();
}
//----------------------------------
// explicitWidth
//----------------------------------
private var _explicitWidth:Number;
/**
* The explicitly specified width for the component,
* in pixels, as the component's coordinates.
* If no width is explicitly specified, the value is NaN
.
*
* @see mx.core.UIComponent#explicitWidth
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get explicitWidth():Number
{
return _explicitWidth;
}
public function set explicitWidth(value:Number):void
{
_explicitWidth = value;
explicitSizeChanged = true;
invalidateParentSizeAndDisplayList();
addEventListener(Event.ENTER_FRAME, enterFrameHandler, false, 0, true);
}
//----------------------------------
// focusPane
//----------------------------------
private var _focusPane:Sprite;
/**
* A single Sprite object that is shared among components
* and used as an overlay for drawing focus.
* Components share this object if their parent is a focused component,
* not if the component implements the IFocusManagerComponent interface.
*
* @see mx.core.UIComponent#focusPane
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get focusPane():Sprite
{
return _focusPane;
}
/**
* @private
*/
public function set focusPane(value:Sprite):void
{
_focusPane = value;
}
//----------------------------------
// includeInLayout
//----------------------------------
private var _includeInLayout:Boolean = true;
/**
* Specifies whether this component is included in the layout of the
* parent container.
* If true
, the object is included in its parent container's
* layout. If false
, the object is positioned by its parent
* container as per its layout rules, but it is ignored for the purpose of
* computing the position of the next child.
*
* @default true
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get includeInLayout():Boolean
{
return _includeInLayout;
}
/**
* @private
*/
public function set includeInLayout(value:Boolean):void
{
_includeInLayout = value;
invalidateParentSizeAndDisplayList();
}
//----------------------------------
// isPopUp
//----------------------------------
private var _isPopUp:Boolean = false;
/**
* Set to true
by the PopUpManager to indicate
* that component has been popped up.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get isPopUp():Boolean
{
return _isPopUp;
}
/**
* @private
*/
public function set isPopUp(value:Boolean):void
{
_isPopUp = value;
}
//----------------------------------
// layer
//----------------------------------
/**
* @private
* Storage for the layer property.
*/
private var _designLayer:DesignLayer;
[Inspectable (environment='none')]
/**
* @copy mx.core.IVisualElement#designLayer
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
public function get designLayer():DesignLayer
{
return _designLayer;
}
/**
* @private
*/
public function set designLayer(value:DesignLayer):void
{
if (_designLayer)
_designLayer.removeEventListener("layerPropertyChange", layer_PropertyChange, false);
_designLayer = value;
if (_designLayer)
_designLayer.addEventListener("layerPropertyChange", layer_PropertyChange, false, 0, true);
super.alpha = _designLayer ? _alpha * _designLayer.effectiveAlpha : _alpha;
super.visible = _designLayer ? _visible && _designLayer.effectiveVisibility : _visible;
}
//----------------------------------
// maxHeight
//----------------------------------
/**
* Number that specifies the maximum height of the component,
* in pixels, as the component's coordinates.
*
* @see mx.core.UIComponent#maxHeight
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get maxHeight():Number
{
return isNaN(explicitMaxHeight) ? 10000 : explicitMaxHeight;
}
public function set maxHeight(value:Number):void
{
explicitMaxHeight = value;
}
//----------------------------------
// maxWidth
//----------------------------------
/**
* Number that specifies the maximum width of the component,
* in pixels, as the component's coordinates.
*
* @see mx.core.UIComponent#maxWidth
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get maxWidth():Number
{
return isNaN(explicitMaxWidth) ? 10000 : explicitMaxWidth;
}
public function set maxWidth(value:Number):void
{
explicitMaxWidth = value;
}
//----------------------------------
// measuredMinHeight
//----------------------------------
private var _measuredMinHeight:Number = 0;
/**
* The default minimum height of the component, in pixels.
* This value is set by the measure()
method.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get measuredMinHeight():Number
{
return _measuredMinHeight;
}
/**
* @private
*/
public function set measuredMinHeight(value:Number):void
{
_measuredMinHeight = value;
}
//----------------------------------
// measuredMinWidth
//----------------------------------
private var _measuredMinWidth:Number = 0;
/**
* The default minimum width of the component, in pixels.
* This value is set by the measure()
method.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get measuredMinWidth():Number
{
return _measuredMinWidth;
}
/**
* @private
*/
public function set measuredMinWidth(value:Number):void
{
_measuredMinWidth = value;
}
//----------------------------------
// minHeight
//----------------------------------
/**
* Number that specifies the minimum height of the component,
* in pixels, as the component's coordinates.
*
* @see mx.core.UIComponent#minHeight
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get minHeight():Number
{
if (!isNaN(explicitMinHeight))
return explicitMinHeight;
return measuredMinHeight;
}
public function set minHeight(value:Number):void
{
explicitMinHeight = value;
}
//----------------------------------
// minWidth
//----------------------------------
/**
* Number that specifies the minimum width of the component,
* in pixels, as the component's coordinates.
*
* @see mx.core.UIComponent#minWidth
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get minWidth():Number
{
if (!isNaN(explicitMinWidth))
return explicitMinWidth;
return measuredMinWidth;
}
public function set minWidth(value:Number):void
{
explicitMinWidth = value;
}
//----------------------------------
// moduleFactory
//----------------------------------
/**
* @private
* Storage for the moduleFactory property.
*/
private var _moduleFactory:IFlexModuleFactory;
[Inspectable(environment="none")]
/**
* A module factory is used as context for using embeded fonts and for
* finding the style manager that controls the styles for this
* component.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 4
*/
public function get moduleFactory():IFlexModuleFactory
{
return _moduleFactory;
}
/**
* @private
*/
public function set moduleFactory(factory:IFlexModuleFactory):void
{
var n:int = numChildren;
for (var i:int = 0; i < n; i++)
{
var child:IFlexModule = getChildAt(i) as IFlexModule;
if (!child)
continue;
if (child.moduleFactory == null || child.moduleFactory == _moduleFactory)
{
child.moduleFactory = factory;
}
}
_moduleFactory = factory;
}
//----------------------------------
// owner
//----------------------------------
private var _owner:DisplayObjectContainer;
/**
* Typically the parent container of this component.
* However, if this is a popup component, the owner is
* the component that popped it up.
* For example, the owner of a dropdown list of a ComboBox control
* is the ComboBox control itself.
* This property is not managed by Flex, but
* by each component.
* Therefore, if you popup a component,
* you should set this property accordingly.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get owner():DisplayObjectContainer
{
return _owner ? _owner : parent;
}
/**
* @private
*/
public function set owner(value:DisplayObjectContainer):void
{
_owner = value;
}
//----------------------------------
// percentHeight
//----------------------------------
private var _percentHeight:Number;
/**
* Number that specifies the height of a component as a
* percentage of its parent's size.
* Allowed values are 0 to 100.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get percentHeight():Number
{
return _percentHeight;
}
public function set percentHeight(value:Number):void
{
_percentHeight = value;
invalidateParentSizeAndDisplayList();
}
//----------------------------------
// percentWidth
//----------------------------------
private var _percentWidth:Number;
/**
* Number that specifies the width of a component as a
* percentage of its parent's size.
* Allowed values are 0 to 100.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get percentWidth():Number
{
return _percentWidth;
}
public function set percentWidth(value:Number):void
{
_percentWidth = value;
invalidateParentSizeAndDisplayList();
}
//----------------------------------
// systemManager
//----------------------------------
private var _systemManager:ISystemManager;
/**
* A reference to the SystemManager object for this component.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get systemManager():ISystemManager
{
if (!_systemManager)
{
var r:DisplayObject = root;
if (r && !(r is Stage))
{
// If this object is attached to the display list, then
// the root property holds its SystemManager.
_systemManager = (r as ISystemManager);
}
else if (r)
{
// if the root is the Stage, then we are in a second AIR window
_systemManager = Stage(r).getChildAt(0) as ISystemManager;
}
else
{
// If this object isn't attached to the display list, then
// we need to walk up the parent chain ourselves.
var o:DisplayObjectContainer = parent;
while (o)
{
var ui:IUIComponent = o as IUIComponent;
if (ui)
{
_systemManager = ui.systemManager;
break;
}
else if (o is ISystemManager)
{
_systemManager = o as ISystemManager;
break;
}
o = o.parent;
}
}
}
return _systemManager;
}
/**
* @private
*/
public function set systemManager(value:ISystemManager):void
{
_systemManager = value;
}
//----------------------------------
// tweeningProperties
//----------------------------------
private var _tweeningProperties:Array;
/**
* Used by EffectManager.
* Returns non-null if a component
* is not using the EffectManager to execute a Tween.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get tweeningProperties():Array
{
return _tweeningProperties;
}
/**
* @private
*/
public function set tweeningProperties(value:Array):void
{
_tweeningProperties = value;
}
//----------------------------------
// visible
//----------------------------------
/**
* @private
* Storage for the visible property.
*/
private var _visible:Boolean = true;
/**
* Whether or not the display object is visible.
* Display objects that are not visible are disabled.
* For example, if visible=false
for an InteractiveObject instance,
* it cannot be clicked.
*
* When setting to true
, the object dispatches
* a show
event.
* When setting to false
, the object dispatches
* a hide
event.
* In either case the children of the object does not emit a
* show
or hide
event unless the object
* has specifically written an implementation to do so.
This is typically hard-coded for graphical skins
* because this number is simply the number of pixels in the graphic.
* For code skins, it can also be hard-coded
* if you expect to be drawn at a certain size.
* If your size can change based on properties, you may want
* to also be an ILayoutManagerClient so a measure()
* method will be called at an appropriate time,
* giving you an opportunity to compute a measuredHeight
.
This is typically hard-coded for graphical skins
* because this number is simply the number of pixels in the graphic.
* For code skins, it can also be hard-coded
* if you expect to be drawn at a certain size.
* If your size can change based on properties, you may want
* to also be an ILayoutManagerClient so a measure()
* method will be called at an appropriate time,
* giving you an opportunity to compute a measuredHeight
.
The default value is 1.0, which means that the object
* is not scaled.
* A scaleX
of 2.0 means the object has been
* magnified by a factor of 2, and a scaleX
of 0.5
* means the object has been reduced by a factor of 2.
A value of 0.0 is an invalid value.
* Rather than setting it to 0.0, set it to a small value, or set
* the visible
property to false
to hide the component.
The default value is 1.0, which means that the object
* is not scaled.
* A scaleY
of 2.0 means the object has been
* magnified by a factor of 2, and a scaleY
of 0.5
* means the object has been reduced by a factor of 2.
A value of 0.0 is an invalid value.
* Rather than setting it to 0.0, set it to a small value, or set
* the visible
property to false
to hide the component.
A scaling along the z axis will not affect a typical component, which lies flat * in the z=0 plane. components with children that have 3D transforms applied, or * components with a non-zero transformZ, will be affected.
* *The default value is 1.0, which means that the object * is not scaled.
* *This property is ignored during calculation by any of Flex's 2D layouts.
* * @default 1.0 * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.1 * @productversion Flex 3 */ override public function get scaleZ():Number { return (_layoutFeatures == null) ? super.scaleZ : _layoutFeatures.layoutScaleZ; } /** * @private */ override public function set scaleZ(value:Number):void { if (scaleZ == value) return; if (_layoutFeatures == null) initAdvancedLayoutFeatures(); hasDeltaIdentityTransform = false; _layoutFeatures.layoutScaleZ = value; invalidateTransform(); //invalidateProperties(); invalidateParentSizeAndDisplayList(); } //-------------------------------------------------------------------------- // // IToolTipManagerClient properties // //-------------------------------------------------------------------------- //---------------------------------- // toolTip //---------------------------------- private var _toolTip:String; /** * Text to display in the ToolTip. * * @default null * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get toolTip():String { return _toolTip; } /** * @private */ public function set toolTip(value:String):void { var toolTipManager:* = ApplicationDomain.currentDomain.getDefinition( "mx.managers.ToolTipManager"); var oldValue:String = _toolTip; _toolTip = value; if (toolTipManager) toolTipManager.registerToolTip(this, oldValue, value); } //-------------------------------------------------------------------------- // // IFocusManagerComponent properties // //-------------------------------------------------------------------------- //---------------------------------- // focusEnabled //---------------------------------- private var _focusEnabled:Boolean = true; /** * A flag that indicates whether the component can receive focus when selected. * *As an optimization, if a child component in your component
* implements the IFocusManagerComponent interface, and you
* never want it to receive focus,
* you can set focusEnabled
* to false
before calling addChild()
* on the child component.
This will cause the FocusManager to ignore this component
* and not monitor it for changes to the tabFocusEnabled
,
* tabChildren
, and mouseFocusEnabled
properties.
* This also means you cannot change this value after
* addChild()
and expect the FocusManager to notice.
Note: It does not mean that you cannot give this object focus
* programmatically in your setFocus()
method;
* it just tells the FocusManager to ignore this IFocusManagerComponent
* component in the Tab and mouse searches.
false
, focus will be transferred to
* the first parent that is mouseFocusEnabled
.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get mouseFocusEnabled():Boolean
{
return false;
}
//----------------------------------
// tabFocusEnabled
//----------------------------------
/**
* @private
* Storage for the tabFocusEnabled property.
*/
private var _tabFocusEnabled:Boolean = true;
[Bindable("tabFocusEnabledChange")]
[Inspectable(defaultValue="true")]
/**
* A flag that indicates whether child objects can receive focus
*
* This is similar to the tabEnabled
property
* used by the Flash Player.
This is usually true
for components that
* handle keyboard input, but some components in controlbars
* have them set to false
because they should not steal
* focus from another component like an editor.
*
rotation
property.
* If you want the layout to not adjust for the component being rotated, you set its postLayoutTransformOffsets.rotationZ
* property.
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
public function set postLayoutTransformOffsets(value:TransformOffsets):void
{
if (_layoutFeatures == null)
initAdvancedLayoutFeatures();
if (_layoutFeatures.postLayoutTransformOffsets != null)
_layoutFeatures.postLayoutTransformOffsets.removeEventListener(Event.CHANGE,transformOffsetsChangedHandler);
_layoutFeatures.postLayoutTransformOffsets = value;
if (_layoutFeatures.postLayoutTransformOffsets != null)
_layoutFeatures.postLayoutTransformOffsets.addEventListener(Event.CHANGE,transformOffsetsChangedHandler);
invalidateTransform();
}
/**
* @private
*/
public function get postLayoutTransformOffsets():TransformOffsets
{
return (_layoutFeatures != null)? _layoutFeatures.postLayoutTransformOffsets:null;
}
private function transformOffsetsChangedHandler(e:Event):void
{
invalidateTransform();
}
/**
* @private
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
override public function get transform():flash.geom.Transform
{
if (_transform == null)
{
setTransform(new mx.geom.Transform(this));
}
return _transform;
}
/**
* @private
*/
override public function set transform(value:flash.geom.Transform):void
{
var m:Matrix = value.matrix;
var m3:Matrix3D = value.matrix3D;
var ct:ColorTransform = value.colorTransform;
var pp:PerspectiveProjection = value.perspectiveProjection;
var mxTransform:mx.geom.Transform = value as mx.geom.Transform;
if (mxTransform)
{
if (!mxTransform.applyMatrix)
m = null;
if (!mxTransform.applyMatrix3D)
m3 = null;
}
setTransform(value);
if (m != null)
setLayoutMatrix(m.clone(), true /*triggerLayoutPass*/);
else if (m3 != null)
setLayoutMatrix3D(m3.clone(), true /*triggerLayoutPass*/);
super.transform.colorTransform = ct;
super.transform.perspectiveProjection = pp;
if (maintainProjectionCenter)
applyPerspectiveProjection();
}
/**
* Documentation is not currently available
*/
mx_internal function get $transform():flash.geom.Transform
{
return super.transform;
}
/**
* @private
*/
private var _maintainProjectionCenter:Boolean = false;
/**
* When true, the component will keep its projection matrix centered on the
* middle of its bounding box. If no projection matrix is defined on the
* component, one will be added automatically.
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
public function set maintainProjectionCenter(value:Boolean):void
{
_maintainProjectionCenter = value;
if (value && super.transform.perspectiveProjection == null)
{
super.transform.perspectiveProjection = new PerspectiveProjection();
}
applyPerspectiveProjection();
}
/**
* @private
*/
public function get maintainProjectionCenter():Boolean
{
return _maintainProjectionCenter;
}
/**
* @inheritDoc
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
public function getLayoutMatrix():Matrix
{
if (_layoutFeatures != null || super.transform.matrix == null)
{
// TODO: this is a workaround for a situation in which the
// object is in 2D, but used to be in 3D and the player has not
// yet cleaned up the matrices. So the matrix property is null, but
// the matrix3D property is non-null. layoutFeatures can deal with
// that situation, so we allocate it here and let it handle it for
// us. The downside is that we have now allocated layoutFeatures
// forever and will continue to use it for future situations that
// might not have required it. Eventually, we should recognize
// situations when we can de-allocate layoutFeatures and back off
// to letting the player handle transforms for us.
if (_layoutFeatures == null)
initAdvancedLayoutFeatures();
// esg: _layoutFeatures keeps a single internal copy of the layoutMatrix.
// since this is an internal class, we don't need to worry about developers
// accidentally messing with this matrix, _unless_ we hand it out. Instead,
// we hand out a clone.
return _layoutFeatures.layoutMatrix.clone();
}
else
{
// flash also returns copies.
return super.transform.matrix;
}
}
/**
* @inheritDoc
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
public function setLayoutMatrix(value:Matrix, invalidateLayout:Boolean):void
{
hasDeltaIdentityTransform = false;
if (_layoutFeatures == null)
{
// flash will make a copy of this on assignment.
super.transform.matrix = value;
}
else
{
// layout features will internally make a copy of this matrix rather than
// holding onto a reference to it.
_layoutFeatures.layoutMatrix = value;
invalidateTransform();
}
//invalidateProperties();
if (invalidateLayout)
invalidateParentSizeAndDisplayList();
}
/**
* @inheritDoc
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
public function getLayoutMatrix3D():Matrix3D
{
if (_layoutFeatures == null)
initAdvancedLayoutFeatures();
// esg: _layoutFeatures keeps a single internal copy of the layoutMatrix.
// since this is an internal class, we don't need to worry about developers
// accidentally messing with this matrix, _unless_ we hand it out. Instead,
// we hand out a clone.
return _layoutFeatures.layoutMatrix3D.clone();
}
/**
* @inheritDoc
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
public function get hasLayoutMatrix3D():Boolean
{
return _layoutFeatures ? _layoutFeatures.layoutIs3D : false;
}
/**
* @inheritDoc
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
public function get is3D():Boolean
{
return _layoutFeatures ? _layoutFeatures.is3D : false;
}
/**
* @inheritDoc
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
public function setLayoutMatrix3D(value:Matrix3D, invalidateLayout:Boolean):void
{
if (_layoutFeatures == null)
initAdvancedLayoutFeatures();
// layout features will internally make a copy of this matrix rather than
// holding onto a reference to it.
_layoutFeatures.layoutMatrix3D = value;
invalidateTransform();
//invalidateProperties();
if (invalidateLayout)
invalidateParentSizeAndDisplayList();
}
private function setTransform(value:flash.geom.Transform):void
{
// Clean up the old transform
var oldTransform:mx.geom.Transform = _transform as mx.geom.Transform;
if (oldTransform)
oldTransform.target = null;
var newTransform:mx.geom.Transform = value as mx.geom.Transform;
if (newTransform)
newTransform.target = this;
_transform = value;
}
/**
* A utility method to update the rotation, scale, and translation of the
* transform while keeping a particular point, specified in the component's
* own coordinate space, fixed in the parent's coordinate space.
* This function will assign the rotation, scale, and translation values
* provided, then update the x/y/z properties as necessary to keep
* the transform center fixed.
*
* @param transformCenter The point, in the component's own coordinates, to keep fixed relative to its parent.
*
* @param scale The new values for the scale of the transform
*
* @param rotation The new values for the rotation of the transform
*
* @param translation The new values for the translation of the transform
*
* @param postLayoutScale
*
* @param postLayoutRotation
*
* @param postLayoutTranslation
*
* @param invalidateLayout
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
public function transformAround(transformCenter:Vector3D,
scale:Vector3D = null,
rotation:Vector3D = null,
translation:Vector3D = null,
postLayoutScale:Vector3D = null,
postLayoutRotation:Vector3D = null,
postLayoutTranslation:Vector3D = null,
invalidateLayout:Boolean = true):void
{
// Make sure that no transform setters will trigger parent invalidation.
// Reset the flag at the end of the method.
var oldIncludeInLayout:Boolean;
if (!invalidateLayout)
{
oldIncludeInLayout = _includeInLayout;
_includeInLayout = false;
}
TransformUtil.transformAround(this,
transformCenter,
scale,
rotation,
translation,
postLayoutScale,
postLayoutRotation,
postLayoutTranslation,
_layoutFeatures,
initAdvancedLayoutFeatures);
if (_layoutFeatures != null)
{
invalidateTransform();
// Will not invalidate parent if we have set _includeInLayout to false
// in the beginning of the method
invalidateParentSizeAndDisplayList();
}
if (!invalidateLayout)
_includeInLayout = oldIncludeInLayout;
}
/**
* A utility method to transform a point specified in the local
* coordinates of this object to its location in the object's parent's
* coordinates. The pre-layout and post-layout result will be set on
* the position
and postLayoutPosition
* parameters, if they are non-null.
*
* @param localPosition The point to be transformed, specified in the
* local coordinates of the object.
* @position A Vector3D point that will hold the pre-layout
* result. If null, the parameter is ignored.
* @postLayoutPosition A Vector3D point that will hold the post-layout
* result. If null, the parameter is ignored.
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
public function transformPointToParent(localPosition:Vector3D,
position:Vector3D,
postLayoutPosition:Vector3D):void
{
TransformUtil.transformPointToParent(this,
localPosition,
position,
postLayoutPosition,
_layoutFeatures);
}
/**
* Helper method to invalidate parent size and display list if
* this object affects its layout (includeInLayout is true).
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
protected function invalidateParentSizeAndDisplayList():void
{
if (!includeInLayout)
return;
var p:IInvalidating = parent as IInvalidating;
if (!p)
return;
p.invalidateSize();
p.invalidateDisplayList();
}
/**
* @private
*
* storage for advanced layout and transform properties.
*/
mx_internal var _layoutFeatures:AdvancedLayoutFeatures;
/**
* @private
* When true, the transform on this component consists only of translation.
* Otherwise, it may be arbitrarily complex.
*/
protected var hasDeltaIdentityTransform:Boolean = true;
/**
* @private
* Storage for the modified Transform object that can dispatch
* change events correctly.
*/
private var _transform:flash.geom.Transform;
/**
* @private
* Initializes the implementation and storage of some of the less
* frequently used advanced layout features of a component.
* Call this function before attempting to use any of the
* features implemented by the AdvancedLayoutFeatures object.
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
private function initAdvancedLayoutFeatures():AdvancedLayoutFeatures
{
var features:AdvancedLayoutFeatures = new AdvancedLayoutFeatures();
hasDeltaIdentityTransform = false;
features.layoutScaleX = scaleX;
features.layoutScaleY = scaleY;
features.layoutScaleZ = scaleZ;
features.layoutRotationX = rotationX;
features.layoutRotationY = rotationY;
features.layoutRotationZ = rotation;
features.layoutX = x;
features.layoutY = y;
features.layoutZ = z;
features.layoutWidth = _width; // for the mirror transform
// Initialize the internal variable last,
// since the transform getters depend on it.
_layoutFeatures = features;
invalidateTransform();
return features;
}
private function invalidateTransform():void
{
if (_layoutFeatures && _layoutFeatures.updatePending == false)
{
_layoutFeatures.updatePending = true;
applyComputedMatrix();
}
}
/**
* Commits the computed matrix built from the combination of the layout matrix and the transform offsets to the flash displayObject's transform.
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
private function applyComputedMatrix():void
{
_layoutFeatures.updatePending = false;
if (_layoutFeatures.is3D)
{
super.transform.matrix3D = _layoutFeatures.computedMatrix3D;
}
else
{
super.transform.matrix = _layoutFeatures.computedMatrix;
}
}
private function applyPerspectiveProjection():void
{
var pmatrix:PerspectiveProjection = super.transform.perspectiveProjection;
if (pmatrix != null)
{
// width, height instead of unscaledWidth, unscaledHeight
pmatrix.projectionCenter = new Point(width/2,height/2);
}
}
//--------------------------------------------------------------------------
//
// Methods
//
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
//
// ILayoutElement
//
//--------------------------------------------------------------------------
/**
* @inheritDoc
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
public function getPreferredBoundsWidth(postLayoutTransform:Boolean = true):Number
{
return LayoutElementUIComponentUtils.getPreferredBoundsWidth(this,postLayoutTransform? nonDeltaLayoutMatrix():null);
}
/**
* @inheritDoc
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
public function getPreferredBoundsHeight(postLayoutTransform:Boolean = true):Number
{
return LayoutElementUIComponentUtils.getPreferredBoundsHeight(this,postLayoutTransform? nonDeltaLayoutMatrix():null);
}
/**
* @inheritDoc
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
public function getMinBoundsWidth(postLayoutTransform:Boolean = true):Number
{
return LayoutElementUIComponentUtils.getMinBoundsWidth(this,postLayoutTransform? nonDeltaLayoutMatrix():null);
}
/**
* @inheritDoc
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
public function getMinBoundsHeight(postLayoutTransform:Boolean = true):Number
{
return LayoutElementUIComponentUtils.getMinBoundsHeight(this,postLayoutTransform? nonDeltaLayoutMatrix():null);
}
/**
* @inheritDoc
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
public function getMaxBoundsWidth(postLayoutTransform:Boolean = true):Number
{
return LayoutElementUIComponentUtils.getMaxBoundsWidth(this,postLayoutTransform? nonDeltaLayoutMatrix():null);
}
/**
* @inheritDoc
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
public function getMaxBoundsHeight(postLayoutTransform:Boolean = true):Number
{
return LayoutElementUIComponentUtils.getMaxBoundsHeight(this,postLayoutTransform? nonDeltaLayoutMatrix():null);
}
/**
* @inheritDoc
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
public function getBoundsXAtSize(width:Number, height:Number, postLayoutTransform:Boolean = true):Number
{
return LayoutElementUIComponentUtils.getBoundsXAtSize(this, width, height,
postLayoutTransform ? nonDeltaLayoutMatrix() : null);
}
/**
* @inheritDoc
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
public function getBoundsYAtSize(width:Number, height:Number, postLayoutTransform:Boolean = true):Number
{
return LayoutElementUIComponentUtils.getBoundsYAtSize(this, width, height,
postLayoutTransform ? nonDeltaLayoutMatrix() : null);
}
/**
* @inheritDoc
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
public function getLayoutBoundsWidth(postLayoutTransform:Boolean = true):Number
{
return LayoutElementUIComponentUtils.getLayoutBoundsWidth(this,postLayoutTransform? nonDeltaLayoutMatrix():null);
}
/**
* @inheritDoc
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
public function getLayoutBoundsHeight(postLayoutTransform:Boolean = true):Number
{
return LayoutElementUIComponentUtils.getLayoutBoundsHeight(this,postLayoutTransform? nonDeltaLayoutMatrix():null);
}
/**
* @inheritDoc
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
public function getLayoutBoundsX(postLayoutTransform:Boolean = true):Number
{
return LayoutElementUIComponentUtils.getLayoutBoundsX(this,postLayoutTransform? nonDeltaLayoutMatrix():null);
}
/**
* @inheritDoc
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
public function getLayoutBoundsY(postLayoutTransform:Boolean = true):Number
{
return LayoutElementUIComponentUtils.getLayoutBoundsY(this,postLayoutTransform? nonDeltaLayoutMatrix():null);
}
/**
* @inheritDoc
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
public function setLayoutBoundsPosition(x:Number, y:Number, postLayoutTransform:Boolean = true):void
{
LayoutElementUIComponentUtils.setLayoutBoundsPosition(this,x,y,postLayoutTransform? nonDeltaLayoutMatrix():null);
}
/**
* @inheritDoc
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
public function setLayoutBoundsSize(width:Number,
height:Number,
postLayoutTransform:Boolean = true):void
{
LayoutElementUIComponentUtils.setLayoutBoundsSize(this,width,height,postLayoutTransform? nonDeltaLayoutMatrix():null);
}
/**
* @private
* Returns the layout matrix, or null if it only consists of translations.
*/
private function nonDeltaLayoutMatrix():Matrix
{
if (hasDeltaIdentityTransform)
return null;
if (_layoutFeatures != null)
{
return _layoutFeatures.layoutMatrix;
}
else
{
// Lose scale
// if scale is actually set (and it's not just our "secret scale"), then
// layoutFeatures wont' be null and we won't be down here
return MatrixUtil.composeMatrix(x, y, 1, 1, rotation,
transformX, transformY);
}
}
//--------------------------------------------------------------------------
//
// Properties
//
//--------------------------------------------------------------------------
//----------------------------------
// bounds
//----------------------------------
/**
* The unscaled bounds of the content.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected function get bounds():Rectangle
{
if (boundingBoxName && boundingBoxName != ""
&& boundingBoxName in this && this[boundingBoxName])
{
return this[boundingBoxName].getBounds(this);
}
return getBounds(this);
}
//----------------------------------
// parent
//----------------------------------
/**
* @private
* Override the parent getter to skip non-UIComponent parents.
*/
override public function get parent():DisplayObjectContainer
{
return _parent ? _parent : super.parent;
}
//----------------------------------
// parentDocument
//----------------------------------
/**
* The document containing this component.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get parentDocument():Object
{
if (document == this)
{
var p:IUIComponent = parent as IUIComponent;
if (p)
return p.document;
var sm:ISystemManager = parent as ISystemManager;
if (sm)
return sm.document;
return null;
}
else
{
return document;
}
}
//----------------------------------
// currentState
//----------------------------------
private var _currentState:String;
/**
* The current state of this component. For UIMovieClip, the value of the
* currentState
property is the current frame label.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get currentState():String
{
return _currentState;
}
public function set currentState(value:String):void
{
if (value == _currentState)
return;
if (!stateMap)
buildStateMap();
if (stateMap[value])
{
// See if we have a transition. The first place to looks is for a specific
// transition between the old and new states.
var frameName:String = _currentState + "-" + value + ":start";
var startFrame:Number;
var endFrame:Number;
if (stateMap[frameName])
{
startFrame = stateMap[frameName].frame;
endFrame = stateMap[_currentState + "-" + value + ":end"].frame;
}
if (isNaN(startFrame))
{
// Next, look for new-old to play backwards
frameName = value + "-" + _currentState + ":end";
if (stateMap[frameName])
{
startFrame = stateMap[frameName].frame;
endFrame = stateMap[value + "-" + _currentState + ":start"].frame;
}
}
if (isNaN(startFrame))
{
// Next, look for *-new
frameName = "*-" + value + ":start";
if (stateMap[frameName])
{
startFrame = stateMap[frameName].frame;
endFrame = stateMap["*-" + value + ":end"].frame;
}
}
if (isNaN(startFrame))
{
// Next, look for new-* to play backwards
frameName = value + "-*:end";
if (stateMap[frameName])
{
startFrame = stateMap[frameName].frame;
endFrame = stateMap[value + "-*:start"].frame;
}
}
if (isNaN(startFrame))
{
// Next, look for old-*
frameName = _currentState + "-*:start";
if (stateMap[frameName])
{
startFrame = stateMap[frameName].frame;
endFrame = stateMap[_currentState + "-*:end"].frame;
}
}
if (isNaN(startFrame))
{
// Next, look for *-old to play backwards
frameName = "*-" + _currentState + ":end";
if (stateMap[frameName])
{
startFrame = stateMap[frameName].frame;
endFrame = stateMap["*-" + _currentState + ":start"].frame;
}
}
if (isNaN(startFrame))
{
// Next, look for *-*
frameName = "*-*:start";
if (stateMap[frameName])
{
startFrame = stateMap[frameName].frame;
endFrame = stateMap["*-*:end"].frame;
}
}
// Finally, just look for the frame of the new state.
if (isNaN(startFrame) && (value in stateMap))
{
startFrame = stateMap[value].frame;
}
// If, after all that searching, we still haven't found a frame to go to, let's
// get outta here.
if (isNaN(startFrame))
return;
var event:StateChangeEvent = new StateChangeEvent(StateChangeEvent.CURRENT_STATE_CHANGING);
event.oldState = _currentState;
event.newState = value;
dispatchEvent(event);
if (isNaN(endFrame))
{
// No transtion - go immediately to the state
gotoAndStop(startFrame);
transitionDirection = 0;
}
else
{
addEventListener(Event.ENTER_FRAME, transitionEnterFrameHandler, false, 0, true);
// If the new transition is starting inside the current transition, start from
// the current frame location.
if (currentFrame < Math.min(startFrame, endFrame) || currentFrame > Math.max(startFrame, endFrame))
gotoAndStop(startFrame);
else
startFrame = currentFrame;
transitionStartFrame = startFrame;
transitionEndFrame = endFrame;
transitionDirection = (endFrame > startFrame) ? 1 : -1;
transitionEndState = value;
}
event = new StateChangeEvent(StateChangeEvent.CURRENT_STATE_CHANGE);
event.oldState = _currentState;
event.newState = value;
dispatchEvent(event);
_currentState = value;
}
}
/**
* @private
*/
override public function get tabEnabled():Boolean
{
return super.tabEnabled;
}
/**
* @private
*/
override public function set tabEnabled(value:Boolean):void
{
super.tabEnabled = value;
explicitTabEnabledChanged = true;
}
//--------------------------------------------------------------------------
//
// IUIComponent methods
//
//--------------------------------------------------------------------------
/**
* Initialize the object.
*
* @see mx.core.UIComponent#initialize()
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function initialize():void
{
initialized = true;
dispatchEvent(new FlexEvent(FlexEvent.PREINITIALIZE));
// Hide the bounding box, if present
if (boundingBoxName && boundingBoxName != ""
&& boundingBoxName in this && this[boundingBoxName])
{
this[boundingBoxName].visible = false;
}
// get the size before we add children or anything else
validateMeasuredSize();
// Location check.
if (isNaN(oldX))
oldX = x;
if (isNaN(oldY))
oldY = y;
if (isNaN(oldWidth))
oldWidth = _width = measuredWidth;
if (isNaN(oldHeight))
oldHeight = _height = measuredHeight;
// Set initial explicit size, if needed
if (explicitSizeChanged)
{
explicitSizeChanged = false;
setActualSize(getExplicitOrMeasuredWidth(), getExplicitOrMeasuredHeight());
}
// Look for focus candidates
findFocusCandidates(this);
// Call initialize() on any IUIComponent children
for (var i:int = 0; i < numChildren; i++)
{
var child:IUIComponent = getChildAt(i) as IUIComponent;
if (child)
child.initialize();
}
dispatchEvent(new FlexEvent(FlexEvent.INITIALIZE));
dispatchEvent(new FlexEvent(FlexEvent.CREATION_COMPLETE));
}
/**
* Called by Flex when a UIComponent object is added to or removed from a parent.
* Developers typically never need to call this method.
*
* @param p The parent of this UIComponent object.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function parentChanged(p:DisplayObjectContainer):void
{
if (!p)
{
_parent = null;
}
else if (p is IUIComponent || p is ISystemManager)
{
_parent = p;
}
else
{
_parent = p.parent;
}
}
/**
* A convenience method for determining whether to use the
* explicit or measured width
*
* @return A Number which is explicitWidth if defined
* or measuredWidth if not.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function getExplicitOrMeasuredWidth():Number
{
if (isNaN(explicitWidth))
{
var mWidth:Number = measuredWidth;
if (!isNaN(explicitMinWidth) && mWidth < explicitMinWidth)
mWidth = explicitMinWidth;
if (!isNaN(explicitMaxWidth) && mWidth > explicitMaxWidth)
mWidth = explicitMaxWidth;
return mWidth;
}
return explicitWidth;
}
/**
* A convenience method for determining whether to use the
* explicit or measured height
*
* @return A Number which is explicitHeight if defined
* or measuredHeight if not.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function getExplicitOrMeasuredHeight():Number
{
if (isNaN(explicitHeight))
{
var mHeight:Number = measuredHeight;
if (!isNaN(explicitMinHeight) && mHeight < explicitMinHeight)
mHeight = explicitMinHeight;
if (!isNaN(explicitMaxHeight) && mHeight > explicitMaxHeight)
mHeight = explicitMaxHeight;
return mHeight;
}
return explicitHeight;
}
/**
* Called when the visible
property changes.
* You should set the visible
property to show or hide
* a component instead of calling this method directly.
*
* @param value The new value of the visible
property.
* Specify true
to show the component, and false
to hide it.
*
* @param noEvent If true
, do not dispatch an event.
* If false
, dispatch a show
event when
* the component becomes visible, and a hide
event when
* the component becomes invisible.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function setVisible(value:Boolean, noEvent:Boolean = false):void
{
_visible = value;
if (designLayer && !designLayer.effectiveVisibility)
value = false;
if (super.visible == value)
return;
super.visible = value;
if (!noEvent)
dispatchEvent(new FlexEvent(value ? FlexEvent.SHOW : FlexEvent.HIDE));
}
/**
* Returns true
if the chain of owner
properties
* points from child
to this UIComponent.
*
* @param child A UIComponent.
*
* @return true
if the child is parented or owned by this UIComponent.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function owns(displayObject:DisplayObject):Boolean
{
while (displayObject && displayObject != this)
{
// do a parent walk
if (displayObject is IUIComponent)
displayObject = IUIComponent(displayObject).owner;
else
displayObject = displayObject.parent;
}
return displayObject == this;
}
//--------------------------------------------------------------------------
//
// IFlexDisplayObject methods
//
//--------------------------------------------------------------------------
/**
* Moves this object to the specified x and y coordinates.
*
* @param x The new x-position for this object.
*
* @param y The new y-position for this object.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function move(x:Number, y:Number):void
{
var changed:Boolean = false;
if (x != this.x)
{
if (_layoutFeatures == null)
super.x = x;
else
_layoutFeatures.layoutX = x;
dispatchEvent(new Event("xChanged"));
changed = true;
}
if (y != this.y)
{
if (_layoutFeatures == null)
super.y = y;
else
_layoutFeatures.layoutY = y;
dispatchEvent(new Event("yChanged"));
changed = true;
}
if (changed)
{
invalidateTransform();
dispatchMoveEvent();
}
}
/**
* Sets the actual size of this object.
*
* This method is mainly for use in implementing the
* updateDisplayList()
method, which is where
* you compute this object's actual size based on
* its explicit size, parent-relative (percent) size,
* and measured size.
* You then apply this actual size to the object
* by calling setActualSize()
.
In other situations, you should be setting properties
* such as width
, height
,
* percentWidth
, or percentHeight
* rather than calling this method.
true
, draw the focus indicator,
* otherwise hide it.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function drawFocus(isFocused:Boolean):void
{
}
//--------------------------------------------------------------------------
//
// Layout methods
//
//--------------------------------------------------------------------------
/**
* Validate the measuredWidth and measuredHeight properties to match the
* current size of the content.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
private function validateMeasuredSize():void
{
if (validateMeasuredSizeFlag)
{
validateMeasuredSizeFlag = false;
_measuredWidth = bounds.width;
_measuredHeight = bounds.height;
}
}
/**
* Notify our parent that our size has changed.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected function notifySizeChanged():void
{
invalidateParentSizeAndDisplayList();
}
/**
* @private
*/
private function dispatchMoveEvent():void
{
var moveEvent:MoveEvent = new MoveEvent(MoveEvent.MOVE);
moveEvent.oldX = oldX;
moveEvent.oldY = oldY;
dispatchEvent(moveEvent);
oldX = x;
oldY = y;
}
/**
* @private
*/
protected function dispatchResizeEvent():void
{
var resizeEvent:ResizeEvent = new ResizeEvent(ResizeEvent.RESIZE);
resizeEvent.oldWidth = oldWidth;
resizeEvent.oldHeight = oldHeight;
dispatchEvent(resizeEvent);
oldWidth = width;
oldHeight = height;
}
/**
* @private
*/
protected function sizeChanged(oldValue:Number, newValue:Number):Boolean
{
// Only detect size changes that are greater than 1 pixel. Flex rounds sizes to the nearest
// pixel, which causes infinite resizing if we have a fractional pixel width and are
// detecting changes that are smaller than 1 pixel.
return Math.abs(oldValue - newValue) > 1;
}
//--------------------------------------------------------------------------
//
// Focus methods
//
//--------------------------------------------------------------------------
/**
* Recursively finds all children that have tabEnabled=true and adds them
* to the focusableObjects array.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected function findFocusCandidates(obj:DisplayObjectContainer):void
{
for (var i:int = 0; i < obj.numChildren; i++)
{
var child:InteractiveObject = obj.getChildAt(i) as InteractiveObject;
if (child && child.tabEnabled)
{
focusableObjects.push(child);
if (!explicitTabEnabledChanged)
{
tabEnabled = true;
tabFocusEnabled = true;
}
}
if (child is DisplayObjectContainer)
findFocusCandidates(DisplayObjectContainer(child));
}
}
//--------------------------------------------------------------------------
//
// State/Transition methods
//
//--------------------------------------------------------------------------
/**
* Build a map of state name to labels.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
private function buildStateMap():void
{
var labels:Array = currentLabels;
stateMap = {};
for (var i:int = 0; i < labels.length; i++)
{
stateMap[labels[i].name] = labels[i];
}
}
//--------------------------------------------------------------------------
//
// Event Handlers
//
//--------------------------------------------------------------------------
/**
* This enter frame handler is used when our width, height, x, or y
* value changes. This is so the change can be delayed so that setting
* x and y at the same time only results in one change event.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected function enterFrameHandler(event:Event):void
{
// explicit size change check.
if (explicitSizeChanged)
{
explicitSizeChanged = false;
setActualSize(getExplicitOrMeasuredWidth(), getExplicitOrMeasuredHeight());
}
if (x != oldX || y != oldY)
dispatchMoveEvent();
removeEventListener(Event.ENTER_FRAME, enterFrameHandler);
}
/**
* @private
* This enter frame handler watches the flash object's size to see if
* it has changed. If it's chagned, we will notify our flex parent of
* the change. This size change may also cause the flash component
* to rescale if it's been explicitly sized so it fits within the
* correct bounds.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 4
*/
protected function autoUpdateMeasuredSizeEnterFrameHandler(event:Event):void
{
// Size check.
var currentBounds:Rectangle = bounds;
// take secret scale into account as it's our real width/height
if (_layoutFeatures != null)
{
currentBounds.width *= _layoutFeatures.stretchX;
currentBounds.height *= _layoutFeatures.stretchY;
}
if (sizeChanged(currentBounds.width, oldWidth) || sizeChanged(currentBounds.height, oldHeight))
{
_width = currentBounds.width;
_height = currentBounds.height;
validateMeasuredSizeFlag = true;
notifySizeChanged();
dispatchResizeEvent();
}
else if (sizeChanged(width, oldWidth) || sizeChanged(height, oldHeight))
{
dispatchResizeEvent();
}
}
/**
* @private
* This enter frame handler watches our currentLabel for changes so that it
* can be reflected in the currentState.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 4
*/
protected function autoUpdateCurrentStateEnterFrameHandler(event:Event):void
{
// Check for the current state. This is really only checked for if
// autoUpdateCurrentState == true. This is so that if we magically land
// on a "foo" labelled frame, we return "foo" as the currentState.
if (currentLabel && currentLabel.indexOf(":") < 0 && currentLabel != _currentState)
_currentState = currentLabel;
}
/**
* @private
* Sets up the current state the very first time. This will only run once.
*/
private function setUpFirstCurrentState(event:Event):void
{
// only run this code the very first time.
removeEventListener(Event.ENTER_FRAME, setUpFirstCurrentState);
if (currentLabel && currentLabel.indexOf(":") < 0 && currentLabel != _currentState)
_currentState = currentLabel;
}
/**
* This enter frame handler progresses through transitions.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 4
*/
protected function transitionEnterFrameHandler(event:Event):void
{
// Play the next frame of the transition, if needed.
var newFrame:Number = currentFrame + transitionDirection;
if ((transitionDirection > 0 && newFrame >= transitionEndFrame) ||
(transitionDirection < 0 && newFrame <= transitionEndFrame))
{
gotoAndStop(stateMap[transitionEndState].frame);
transitionDirection = 0;
removeEventListener(Event.ENTER_FRAME, transitionEnterFrameHandler);
}
else
{
gotoAndStop(newFrame);
}
}
/**
* Add the focus event listeners.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
private function addFocusEventListeners():void
{
// If we get a security error because we're not allowed to add event listeners to the stage,
// then just add them to the systemManager instead because we could be an untrusted app.
try
{
stage.addEventListener(FocusEvent.KEY_FOCUS_CHANGE, keyFocusChangeHandler, false, 1, true);
stage.addEventListener(FocusEvent.FOCUS_OUT, focusOutHandler, false, 0, true);
}
catch (err:SecurityError)
{
systemManager.addEventListener(FocusEvent.KEY_FOCUS_CHANGE, keyFocusChangeHandler, false, 1, true);
systemManager.addEventListener(FocusEvent.FOCUS_OUT, focusOutHandler, false, 0, true);
}
focusListenersAdded = true;
}
/**
* Remove our focus event listeners.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
private function removeFocusEventListeners():void
{
// Same security issue as addFocusEventListeners()
try
{
if (stage)
{
stage.removeEventListener(FocusEvent.KEY_FOCUS_CHANGE, keyFocusChangeHandler);
stage.removeEventListener(FocusEvent.FOCUS_OUT, focusOutHandler);
}
}
catch (err:SecurityError)
{
systemManager.removeEventListener(FocusEvent.KEY_FOCUS_CHANGE, keyFocusChangeHandler);
systemManager.removeEventListener(FocusEvent.FOCUS_OUT, focusOutHandler);
}
focusListenersAdded = false;
}
/**
* Called when the focus is changed by keyboard navigation (TAB or Shift+TAB).
* If we are currently managing the focus, stop the event propagation to
* "steal" the event from the Flex focus manager.
* If we are at the end of our focusable items (first item for Shift+TAB, or
* last item for TAB), remove our event handlers to give control back
* to the Flex focus manager.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
private function keyFocusChangeHandler(event:FocusEvent):void
{
if (event.keyCode == Keyboard.TAB)
{
if (stage.focus == focusableObjects[event.shiftKey ? 0 : focusableObjects.length - 1])
removeFocusEventListeners();
else
event.stopImmediatePropagation();
}
}
/**
* Called when focus is entering any of our children. Make sure our
* focus event handlers are called so we can take control from the
* Flex focus manager.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected function focusInHandler(event:FocusEvent):void
{
if (!focusListenersAdded)
addFocusEventListeners();
}
/**
* Called when focus is leaving an object. We check to see if the new
* focus item is in our focusableObjects list, and if not we remove
* our event listeners to give control back to the Flex focus manager.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
private function focusOutHandler(event:FocusEvent):void
{
if (focusableObjects.indexOf(event.relatedObject) == -1)
removeFocusEventListeners();
}
/**
* Called during event capture phase when keyboard navigation is changing
* focus. All we do here is set a flag so we know which direction the
* focus is changing - TAB = forward; Shift+TAB = reverse.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
private function keyFocusChangeCaptureHandler(event:FocusEvent):void
{
reverseDirectionFocus = event.shiftKey;
}
private function creationCompleteHandler(event:Event):void
{
removeEventListener(FlexEvent.CREATION_COMPLETE, creationCompleteHandler);
// Add a key focus change handler at the capture phase. We use this to
// determine focus direction in the setFocus() call.
if (systemManager)
{
// If we get a security error because we're not allowed to add event listeners to the stage,
// then just add them to the systemManager instead because we could be an untrusted app.
try
{
systemManager.stage.addEventListener(FocusEvent.KEY_FOCUS_CHANGE, keyFocusChangeCaptureHandler,
true, 0, true);
}
catch (err:SecurityError)
{
systemManager.addEventListener(FocusEvent.KEY_FOCUS_CHANGE, keyFocusChangeCaptureHandler,
true, 0, true);
}
}
else if (parentDocument && parentDocument.systemManager)
{
// Same security issue as above
try
{
parentDocument.systemManager.stage.addEventListener(FocusEvent.KEY_FOCUS_CHANGE, keyFocusChangeCaptureHandler,
true, 0, true);
}
catch (err:SecurityError)
{
parentDocument.systemManager.addEventListener(FocusEvent.KEY_FOCUS_CHANGE, keyFocusChangeCaptureHandler,
true, 0, true);
}
}
}
/**
* @private
*/
protected function layer_PropertyChange(event:PropertyChangeEvent):void
{
switch (event.property)
{
case "effectiveVisibility":
{
var newValue:Boolean = (event.newValue && _visible);
if (newValue != super.visible)
super.visible = newValue;
break;
}
case "effectiveAlpha":
{
var newAlpha:Number = Number(event.newValue) * _alpha;
if (newAlpha != super.alpha)
super.alpha = newAlpha;
break;
}
}
}
// IAutomationObject Interface defenitions
private var _automationDelegate:IAutomationObject;
/**
* The delegate object that handles the automation-related functionality.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get automationDelegate():Object
{
return _automationDelegate;
}
/**
* @private
*/
public function set automationDelegate(value:Object):void
{
_automationDelegate = value as IAutomationObject;
}
//----------------------------------
// automationName
//----------------------------------
/**
* @private
* Storage for the automationName
property.
*/
private var _automationName:String = null;
/**
* @inheritDoc
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get automationName():String
{
if (_automationName)
return _automationName;
if (automationDelegate)
return automationDelegate.automationName;
return "";
}
/**
* @private
*/
public function set automationName(value:String):void
{
_automationName = value;
}
/**
* @copy mx.automation.IAutomationObject#automationValue
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get automationValue():Array
{
if (automationDelegate)
return automationDelegate.automationValue;
return [];
}
//----------------------------------
// automationOwner
//----------------------------------
/**
* @inheritDoc
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 4
*/
public function get automationOwner():DisplayObjectContainer
{
return owner;
}
//----------------------------------
// automationParent
//----------------------------------
/**
* @inheritDoc
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 4
*/
public function get automationParent():DisplayObjectContainer
{
return parent;
}
//----------------------------------
// automationEnabled
//----------------------------------
/**
* @inheritDoc
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 4
*/
public function get automationEnabled():Boolean
{
return enabled;
}
//----------------------------------
// automationVisible
//----------------------------------
/**
* @inheritDoc
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 4
*/
public function get automationVisible():Boolean
{
return visible;
}
//----------------------------------
// showInAutomationHierarchy
//----------------------------------
/**
* @private
* Storage for the showInAutomationHierarchy
property.
*/
private var _showInAutomationHierarchy:Boolean = true;
/**
* @inheritDoc
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get showInAutomationHierarchy():Boolean
{
return _showInAutomationHierarchy;
}
/**
* @private
*/
public function set showInAutomationHierarchy(value:Boolean):void
{
_showInAutomationHierarchy = value;
}
/**
* @inheritDoc
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function createAutomationIDPart(child:IAutomationObject):Object
{
if (automationDelegate)
return automationDelegate.createAutomationIDPart(child);
return null;
}
/**
* @inheritDoc
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
public function createAutomationIDPartWithRequiredProperties(child:IAutomationObject,
properties:Array):Object
{
if (automationDelegate)
return automationDelegate.createAutomationIDPartWithRequiredProperties(child, properties);
return null;
}
/**
* @inheritDoc
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function resolveAutomationIDPart(criteria:Object):Array
{
if (automationDelegate)
return automationDelegate.resolveAutomationIDPart(criteria);
return [];
}
/**
* @inheritDoc
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function getAutomationChildAt(index:int):IAutomationObject
{
if (automationDelegate)
return automationDelegate.getAutomationChildAt(index);
return null;
}
/**
* @inheritDoc
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
public function getAutomationChildren():Array
{
if (automationDelegate)
return automationDelegate.getAutomationChildren();
return null;
}
/**
* @inheritDoc
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get numAutomationChildren():int
{
if (automationDelegate)
return automationDelegate.numAutomationChildren;
return 0;
}
/**
* @inheritDoc
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get automationTabularData():Object
{
if (automationDelegate)
return automationDelegate.automationTabularData;
return null;
}
/**
* @inheritDoc
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function replayAutomatableEvent(event:Event):Boolean
{
if (automationDelegate)
return automationDelegate.replayAutomatableEvent(event);
return false;
}
}
}