PLEASE NOTE THAT THIS SPECIFICATION MAY BE OUT OF DATE, DOCUMENTATION PROVIDED WITH THE RELEASE SUPERCEDES ANYTHING IN THIS SPEC.
The release of Flash CS3 makes it possible to create interactive Flash content that is used directly by Flex 2[*]. This feature introduces a complete workflow for authoring content in Flash that can be seamlessly integrated into Flex.
This integration workflow is oriented towards timeline-based content with simple interactivity. While it is possible to do code-intensive components in Flash that also work in Flex, that is not a primary design goal.
The integration is made possible by a new class named UIMovieClip. This is a lightweight subclass of MovieClip that implements the IFlexDisplayObject and IUIComponent interfaces (and others too, see the API description for the complete list). Any subclass of UIMovieClip can be used as a child of any Flex Container object, or as a skin for any Flex component. The UIMovieClip class is fully functional in Flash, making it possible to develop and test the content in Flash and then integrate it into Flex.
The workflow for integrating static skins into Flex is not being changed. Please refer to NJ's DevNet article for the skinning workflow.
There are two releases planned for this integration kit. The first release targets Flex 2.0.1 Hotfix 2, and will be posted to Labs around the same time as the CS3 release. The second release will be part of Moxie, and includes deeper integration of Flash content for things like skin states and creating containers in Flash.
Note: This spec contains several SWF files inline. You need to click on the SWF file once before you can interact with it.
[*] Yes, it is possible to load pre-CS3 SWF files and make them interactive, but that requires jumping through many hoops and using local connection if you needed to communicate between the Flex and Flash content. Definitely not simple or seamless…
Components authored in Flash for use in Flex must be a subclass of mx.flash.UIMovieClip. The UIMovieClip base class extends MovieClip and implements the core Flex interfaces, allowing the component to be used inside Flex containers and as Flex skins.
The simplest workflow does not require any additional coding in Flash. As long as the base class of the component symbol is set to mx.flash.UIMovieClip, the component will work in Flex. In this case, you do not need to create a subclass for your component. Flash will do this automatically for you.
There are times when you do need to create an explicit subclass of UIMovieClip. Some examples include custom events (the Event metadata needs to be added to the subclass), additional public properties/methods, and modifying any of the default behavior. In this case, you will need to create a new ActionScript file that contains your subclass.
The Flex/Flash integration kit is a ZIP file that contains one directory and a FlexIntegration.mxp file. The directory contains sample files.
This ZIP file should be extracted to your hard disk. The FlexIntegration.mxp file is run to install the required integration files in Flash.
There are a few document-level settings that need to be made before Flex-enabled components can be created in Flash. These settings can be done manually, if you'd like, or will be done automatically when running the "Make Flex Component" command.
The following document settings need to be made in order for Flex content to be authored in Flash. These will be
New item for the Flash "New…" dialog that creates an empty FLA and runs the "Configure Document for Flex Integration" script on it. [can be B-Feature for Labs if needed]
New item for the Flash start page that creates a Flex Integration document. [B-feature]
The registration point for the exported symbol must be the upper left corner. If you have Flash content that has a different registration point you can always wrap the content in a new symbol with an upper left registration point.
In order for the timing to remain consistent, the Flash frame rate must match the Flex frame rate. The default Flex frame rate is 24fps, so it is recommended that the Flash content matches this. If needed, the Flex frame rate can be set to a different value, although this should only be done as a fallback. Setting the Flex frame rate to a value less than 24fsp will cause sluggishness in the UI.
By default, the measured size of the Flash content matches the actual size. Any changes to the content size will automatically be recognized by Flex, and the component will be layed out again in its new size. Here is an example of a Flash component that changes size dynamically:
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:myComps="*" backgroundColor="0xFFFFFF">
<myComps:BlueBox />
<mx:Button />
</mx:Application>
The animation of the BlueBox is triggering a layout every time the size of the box changes, causing the Button underneath it to bounce up and down.
There are a couple of gotchas regarding the auto-size behavior. First, shape tweens are only auto-sized on keyframes. Second, masked content is reported at its full size, not its masked size. Both of these can lead to unexpected sizing results.
You can add a bounds proxy to make the reported size of the content to be different than the actual size. The boundingBoxName property of UIMovieClip specifies the name of an object to use as the bounds proxy for the content. The default value is "boundingBox".
In this next example, the "YellowDot" component explodes when it is clicked. Since we don't want the explosion to change the size or location of the component, we add a boundingBox object that establishes and maintains the correct size for the component.
Here is the content in Flash, with the bounds proxy selected (note: the name "boundsProxy" should be "boundingBox"):
Here is the Flex code:
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:myComps="*"
backgroundColor="0x000000" width="300" height="250">
<mx:Spacer height="80" />
<mx:Label text="Click a dot" color="0xFFFFFF" />
<mx:HBox>
<myComps:YellowDot mouseDown="event.currentTarget.currentState='explode'" />
<myComps:YellowDot mouseDown="event.currentTarget.currentState='explode'" />
<myComps:YellowDot mouseDown="event.currentTarget.currentState='explode'" />
</mx:HBox>
</mx:Application>
UIMovieClip maps Flash frame labels to Flex states. Setting the currentState property jumps the content to the specified frame label (if it exists).
This example shows the Flash timeline with three frame labels defined: "ellipse", "rectangle", and "triangle":
These frame labels are mapped to states in Flex. To go to a particular label, set the currentState property:
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:myComps="*"
backgroundColor="0x000000" width="300" height="250">
<mx:HBox>
<mx:Button label="Ellipse" click="s.currentState='ellipse'" />
<mx:Button label="Rectangle" click="s.currentState='rectangle'" />
<mx:Button label="Triangle" click="s.currentState='triangle'" />
</mx:HBox>
<myComps:Shapes id="s" />
</mx:Application>
Here is the running example:
Transitions for Flash content are defined on the timeline, and are marked by specially named frame labels. When going from state1 to state2, UIMovieClip looks for a frame label named "state1-state2:start" to determine the start frame of the transitions, and a frame label named "state1-state2:end" to determine the end frame.
In this example, the "normal" frame is selected, and the "normal-explode:start" frame label is visible. The "normal-explode:end" label is on Frame 20. When going from the "normal" state to the "explode" state, this set of frames will be played as a transition between the two states.
If the "state1-state2:start" label cannot be found, UIMovieClip looks for a transition for state2-state1 and plays it backwards. Using the previous example, there is a transition defined for normal-explode, but no transition defined for explode-normal. In this case, the normal-explode transition will be run in reverse when going from the "explode" state to the "normal" state.
Transition frame labels support the "" wildcard which means "any state". For example, a label "state1-:start" specifies a transition from "state1" to any other state. Likewise, "*-state1:start" specifies a transition from any state to "state1". The wildcard rules also apply when looking for transitions to play in reverse.
The following priority is used when looking for transitions:
UIMovieClip dispatches all the "standard" Flex component events like move, resize, and currentStateChange. Additionally, custom events can be dispatched from the Flash content and handled inside Flex.
To dispatch custom events, you first need to create a class file for your content. The Event metadata is added to this class. Here is an example: !CustomEvents1.gif|width=675, align=center!
The next step is to dispatch the event. Here is the example that dispatches an alarmEvent: !CustomEvents2.gif|align=center, width=675!
The MXML code handles the alarmEvent just like all other events:
<myComps:Clock alarmEvent="showAlarm()" />
UIMovieClip implements IToolTipManagerClient, which includes the toolTip property. You can set the toolTip property for any Flash content, and the standard Flex tooltip will appear when the mouse is held over the content.
The setActualSize() method can be overridden in order to programmatically respond to size changes within the Flash content. Here is an example that creates a grid of YellowDot components:
package {
import flash.display.DisplayObject;
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.MouseEvent;
import mx.flash.UIMovieClip;
public dynamic class Dots extends UIMovieClip
{
private const SIZE:Number = 36; // Size of column/row
private const GAP:Number = 4;
public function Dots():void
{
}
override public function get measuredWidth():Number
{
return SIZE + GAP + SIZE; // Wide enough for 2 columns and 1 gap
}
override public function get measuredHeight():Number
{
return SIZE + GAP + SIZE; // Tall enough for 2 rows and 1 gap
}
override public function setActualSize(newWidth:Number, newHeight:Number):void
{
if (newWidth != _width || newHeight != _height)
{
_width = newWidth;
_height = newHeight;
// Clear out our existing children
for (var i:int = 0; i < numChildren; i++)
{
removeChildAt(0);
}
// Figure out how many rows/columns to create
var numRows:int = Math.floor((newHeight + GAP) / (SIZE + GAP));
var numCols:int = Math.floor((newWidth + GAP) / (SIZE + GAP));
// Create and place our children
for (var row:int = 0; row < numRows; row++)
{
for (var col:int = 0; col < numCols; col++)
{
var dot:YellowDot = new YellowDot();
addChild(dot);
dot.move(col * (SIZE + GAP), row * (SIZE + GAP));
}
}
}
}
}
}
Any item within the Flash content that has tabEnabled=trueis included in focus/keyboard management. The Flash content is responsible for drawing any focus indicator--you will not get the standard Flex focus highlight.
This requires changes to the FocusManager to notify components how focus was entered (keyboard or mouse), and the direction of travel (tab vs. shift-tab).
The states and transition features mentioned above can be used to create animated skins for use in Moxie. Make sure the state labels correspond to the correct state names for the skins ("up", "down", "over", etc.), and use ClassReference() to assign the content to the skin property.
<mx:Style>
Button {
skin: ClassReference("MyButtonSkin");
}
</mx:Style>
<mx:Button label="Look at me!" />
A new "Make Flex Container" item is added to the Flash Commands menu. This is a companion to the "Make Flex Component" command that turns the selected symbol(s) into a container for Flex content.
Here is a screen shot of the command:
The command adds a new "FlexContentHolder" symbol to the Library. This is the holder for the Flex content. Drag this symbol to the stage, and position/size it where you want the flex content to go. The symbol has a placeholder graphic where the Flex content will appear (the artwork in the screen shot is not final). The placeholder graphic is automatically removed when the component is used inside Flex.
The "Make Flex Container" command sets the base class of the symbol to mx.flash.ContainerMovieClip. This is a subclass of UIMovieClip that adds a content property.
Let's look at some examples. The first one is a simple rectangular content holder that has a mask over the content.
Here is the FLA file where you can see the mask layer and the content layer. The contentHolder object is selected--this is where the Flex content will go. (NOTE: This screenshot uses the symbol name "PanelContents", but it should be "FlexContentHolder". Also note that the placeholder image is not shown. In other words, I'm too damn lazy to take another screenshot…) :-) !MaskedContainerFLA.gif|align=center, width=675!
Here is the mxml. The content property is the default property for ContainerMovieClip, which means the mxml content can go directly inside the Flash component tag (local:MaskedContainer in this case).
<mx:Application ... >
<local:MaskedContainer>
<mx:VBox>
<mx:Button label="Button 1" />
<mx:Button label="Button 2" />
<mx:Button label="Button 3" />
<mx:Button label="Button 4" />
<mx:Button label="Button 5" />
<mx:Button label="Button 6" />
<mx:Button label="Button 7" />
</mx:VBox>
</local:MaskedContainer>
</mx:Application>
Here is the app. Notice how the mask defined in Flash is applied to the Flex content. You can interact with the Button components, but please don't press the Tab key (unless you like seeing RTE dialogs, that is…).
The next example is a collapsing pod component. Here is the FLA file. Note the collapse control in the upper-left corner and the timeline animation for the collapse/expand transition. (NOTE: Once again, this screenshot is out of date and does not use FlexContentHolder or show the content placeholder).
This component required a custom class to add a title property and set an event handler that toggles between the collapsed and expanded states. Here is the code:
package {
import flash.display.MovieClip;
import flash.display.SimpleButton;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.text.TextField;
import mx.flash.ContainerMovieClip;
public class MyPanel extends ContainerMovieClip {
/////////////////////////////////////////////////////////////////////
// Constructor
/////////////////////////////////////////////////////////////////////
public function MyPanel():void
{
resizer.addEventListener(MouseEvent.CLICK, resizer_clickHandler);
resizer.useHandCursor = false;
}
/////////////////////////////////////////////////////////////////////
// Properties
/////////////////////////////////////////////////////////////////////
/////////////////
// title
/////////////////
public function get title():String
{
return titleField.text;
}
public function set title(value:String):void
{
titleField.text = value;
}
/////////////////////////////////////////////////////////////////////
// Event handlers
/////////////////////////////////////////////////////////////////////
private function resizer_clickHandler(event:MouseEvent):void
{
currentState = currentState == "expand" ? "collapse" : "expand";
}
}
}
Here is an alternate version of the pod that supports dynamic resizing (but does not support collapse/expand):
package {
import flash.display.MovieClip;
import flash.display.SimpleButton;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.text.TextField;
import mx.flash.ContainerMovieClip;
public class ResizeablePanel extends ContainerMovieClip {
/////////////////////////////////////////////////////////////////////
// Constructor
/////////////////////////////////////////////////////////////////////
public function ResizeablePanel():void
{
}
/////////////////////////////////////////////////////////////////////
// Properties
/////////////////////////////////////////////////////////////////////
/////////////////
// title
/////////////////
public function get title():String
{
return titleField.text;
}
public function set title(value:String):void
{
titleField.text = value;
}
/////////////////////////////////////////////////////////////////////
// Methods
/////////////////////////////////////////////////////////////////////
override public function setActualSize(newWidth:Number, newHeight:Number):void
{
titleField.width = newWidth;
contentHolder.setActualSize(newWidth - 10, newHeight - 31);
contentHolder.content_bg.width = newWidth - 10;
contentHolder.content_bg.height = newHeight - 31;
background.width = boundingBox.width = newWidth;
background.height = boundingBox.height = newHeight;
_width = newWidth;
_height = newHeight;
}
}
}
And finally, here is an mxml example that uses both of these components. Note how the bottom panel takes up all available space, and automatically resizes when the top panel is collapsed/expanded.
<mx:Application ...>
<local:MyPanel title="Login">
<mx:VBox paddingLeft="5" paddingRight="5">
<mx:Label text="name" />
<mx:TextInput width="100%" />
<mx:Label text="password" />
<mx:TextInput width="100%" />
<mx:Button label="Submit" />
</mx:VBox>
</local:MyPanel>
<local:ResizeablePanel title="Resize Panel" width="100%" height="100%">
<mx:TabNavigator width="100%" height="100%">
<mx:VBox label="One" />
<mx:VBox label="Two" />
</mx:TabNavigator>
</local:ResizeablePanel>
</mx:Application>
Here are some issues to consider regarding Flex content in Flash components
[End of Moxie features section]
This JSFL is run on a Flash Symbol, and does the following steps:
This prepares the symbol for use in Flex.
Here is a screenshot of the Flash Symbol Properties dialog, with the proper settings for Flex content:
Here are the steps required to use the Flash content in FlexBuilder.
//--------------------------------------
// Lifecycle events
//--------------------------------------
/**
* Dispatched when the component is added to a container as a content child
* by using the <code>addChild()</code> or <code>addChildAt()</code> method.
* If the component is added to the container as a noncontent child by
* using the <code>rawChildren.addChild()</code> or
* <code>rawChildren.addChildAt()</code> method, the event is not dispatched.
*
* @eventType mx.events.FlexEvent.ADD
*/
<a href="Event%28name%3D%26quot%3Badd%26quot%3B%2C%20type%3D%26quot%3Bmx.events.FlexEvent%26quot%3B%29">Event(name="add", type="mx.events.FlexEvent")</a>
/**
* Dispatched when an object's state changes from visible to invisible.
*
* @eventType mx.events.FlexEvent.HIDE
*/
<a href="Event%28name%3D%26quot%3Bhide%26quot%3B%2C%20type%3D%26quot%3Bmx.events.FlexEvent%26quot%3B%29">Event(name="hide", type="mx.events.FlexEvent")</a>
/**
* Dispatched when the component has finished its construction
* and has all initialization properties set.
*
* @eventType mx.events.FlexEvent.INITIALIZE
*/
<a href="Event%28name%3D%26quot%3Binitialize%26quot%3B%2C%20type%3D%26quot%3Bmx.events.FlexEvent%26quot%3B%29">Event(name="initialize", type="mx.events.FlexEvent")</a>
/**
* Dispatched when the object has moved.
*
* <p>You can move the component by setting the <code>x</code>
* or <code>y</code> properties, by calling the <code>move()</code>
* method, by setting one
* of the following properties either on the component or on other
* components such that the LayoutManager needs to change the
* <code>x</code> or <code>y</code> properties of the component:</p>
*
* <ul>
* <li><code>minWidth</code></li>
* <li><code>minHeight</code></li>
* <li><code>maxWidth</code></li>
* <li><code>maxHeight</code></li>
* <li><code>explicitWidth</code></li>
* <li><code>explicitHeight</code></li>
* </ul>
*
* <p>When you call the <code>move()</code> method, the <code>move</code>
* event is dispatched before the method returns.
* In all other situations, the <code>move</code> event is not dispatched
* until after the property changes.</p>
*
* @eventType mx.events.MoveEvent.MOVE
*/
<a href="Event%28name%3D%26quot%3Bmove%26quot%3B%2C%20type%3D%26quot%3Bmx.events.MoveEvent%26quot%3B%29">Event(name="move", type="mx.events.MoveEvent")</a>
/**
* Dispatched at the beginning of the component initialization sequence.
* The component is in a very raw state when this event is dispatched.
* Many components, such as the Button control, create internal child
* components to implement functionality; for example, the Button control
* creates an internal UITextField component to represent its label text.
* When Flex dispatches the <code>preinitialize</code> event,
* the children, including the internal children, of a component
* have not yet been created.
*
* @eventType mx.events.FlexEvent.PREINITIALIZE
*/
<a href="Event%28name%3D%26quot%3Bpreinitialize%26quot%3B%2C%20type%3D%26quot%3Bmx.events.FlexEvent%26quot%3B%29">Event(name="preinitialize", type="mx.events.FlexEvent")</a>
/**
* Dispatched when the component is removed from a container as a content child
* by using the <code>removeChild()</code> or <code>removeChildAt()</code> method.
* If the component is removed from the container as a noncontent child by
* using the <code>rawChildren.removeChild()</code> or
* <code>rawChildren.removeChildAt()</code> method, the event is not dispatched.
*
* @eventType mx.events.FlexEvent.REMOVE
*/
<a href="Event%28name%3D%26quot%3Bremove%26quot%3B%2C%20type%3D%26quot%3Bmx.events.FlexEvent%26quot%3B%29">Event(name="remove", type="mx.events.FlexEvent")</a>
/**
* Dispatched when the component is resized.
*
* <p>You can resize the component by setting the <code>width</code> or
* <code>height</code> property, by calling the <code>setActualSize()</code>
* 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 <code>width</code> or
* <code>height</code> properties of the component:</p>
*
* <ul>
* <li><code>minWidth</code></li>
* <li><code>minHeight</code></li>
* <li><code>maxWidth</code></li>
* <li><code>maxHeight</code></li>
* <li><code>explicitWidth</code></li>
* <li><code>explicitHeight</code></li>
* </ul>
*
* <p>The <code>resize</code> event is not
* dispatched until after the property changes.</p>
*
* @eventType mx.events.ResizeEvent.RESIZE
*/
<a href="Event%28name%3D%26quot%3Bresize%26quot%3B%2C%20type%3D%26quot%3Bmx.events.ResizeEvent%26quot%3B%29">Event(name="resize", type="mx.events.ResizeEvent")</a>
/**
* Dispatched when an object's state changes from invisible to visible.
*
* @eventType mx.events.FlexEvent.SHOW
*/
<a href="Event%28name%3D%26quot%3Bshow%26quot%3B%2C%20type%3D%26quot%3Bmx.events.FlexEvent%26quot%3B%29">Event(name="show", type="mx.events.FlexEvent")</a>
//--------------------------------------
// Mouse events
//--------------------------------------
/**
* Dispatched from a component opened using the PopUpManager
* when the user clicks outside it.
*
* @eventType mx.events.FlexMouseEvent.MOUSE_DOWN_OUTSIDE
*/
<a href="Event%28name%3D%26quot%3BmouseDownOutside%26quot%3B%2C%20type%3D%26quot%3Bmx.events.FlexMouseEvent%26quot%3B%29">Event(name="mouseDownOutside", type="mx.events.FlexMouseEvent")</a>
/**
* Dispatched from a component opened using the PopUpManager
* when the user scrolls the mouse wheel outside it.
*
* @eventType mx.events.FlexMouseEvent.MOUSE_WHEEL_OUTSIDE
*/
<a href="Event%28name%3D%26quot%3BmouseWheelOutside%26quot%3B%2C%20type%3D%26quot%3Bmx.events.FlexMouseEvent%26quot%3B%29">Event(name="mouseWheelOutside", type="mx.events.FlexMouseEvent")</a>
//--------------------------------------
// Drag-and-drop events
//--------------------------------------
/**
* Dispatched by a component when the user moves the mouse over the component
* during a drag operation.
*
* <p>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.</p>
*
* <p>If you want to accept the drag, you must call the
* <code>DragManager.acceptDragDrop()</code> method. If you don't
* call <code>acceptDragDrop()</code>, you will not get any of the
* other drag events.</p>
*
* <p>The value of the <code>action</code> property is always
* <code>DragManager.MOVE</code>, even if you are doing a copy.
* This is because the <code>dragEnter</code> event occurs before
* the control recognizes that the Control key is pressed to signal a copy.
* The <code>action</code> property of the event object for the
* <code>dragOver</code> event does contain a value that signifies the type of
* drag operation.</p>
*
* <p>You may change the type of drag action by calling the
* <code>DragManager.showFeedback()</code> method.</p>
*
* @see mx.managers.DragManager
*
* @eventType mx.events.DragEvent.DRAG_ENTER
*/
<a href="Event%28name%3D%26quot%3BdragEnter%26quot%3B%2C%20type%3D%26quot%3Bmx.events.DragEvent%26quot%3B%29">Event(name="dragEnter", type="mx.events.DragEvent")</a>
/**
* Dispatched by a component when the user moves the mouse while over the component
* during a drag operation.
*
* <p>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.</p>
*
* <p>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.</p>
*
* <p>You may also change the type of drag action by changing the
* <code>DragManager.showFeedback()</code> method.
* The default value of the <code>action</code> property is
* <code>DragManager.MOVE</code>.</p>
*
* @see mx.managers.DragManager
*
* @eventType mx.events.DragEvent.DRAG_OVER
*/
<a href="Event%28name%3D%26quot%3BdragOver%26quot%3B%2C%20type%3D%26quot%3Bmx.events.DragEvent%26quot%3B%29">Event(name="dragOver", type="mx.events.DragEvent")</a>
/**
* Dispatched by the component when the user drags outside the component,
* but does not drop the data onto the target.
*
* <p>You use this event to restore the drop target to its normal appearance
* if you modified its appearance as part of handling the
* <code>dragEnter</code> or <code>dragOver</code> event.</p>
*
* @eventType mx.events.DragEvent.DRAG_EXIT
*/
<a href="Event%28name%3D%26quot%3BdragExit%26quot%3B%2C%20type%3D%26quot%3Bmx.events.DragEvent%26quot%3B%29">Event(name="dragExit", type="mx.events.DragEvent")</a>
/**
* Dispatched by the drop target when the user releases the mouse over it.
*
* <p>You use this event handler to add the drag data to the drop target.</p>
*
* <p>If you call <code>Event.preventDefault()</code> in the event handler
* for the <code>dragDrop</code> event for
* a Tree control when dragging data from one Tree control to another,
* it prevents the drop.</p>
*
* @eventType mx.events.DragEvent.DRAG_DROP
*/
<a href="Event%28name%3D%26quot%3BdragDrop%26quot%3B%2C%20type%3D%26quot%3Bmx.events.DragEvent%26quot%3B%29">Event(name="dragDrop", type="mx.events.DragEvent")</a>
/**
* Dispatched by the drag initiator (the component that is the source
* of the data being dragged) when the drag operation completes,
* either when you drop the dragged data onto a drop target or when you end
* the drag-and-drop operation without performing a drop.
*
* <p>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.</p>
*
* <p>If you call <code>Event.preventDefault()</code> in the event handler
* for the <code>dragComplete</code> event for
* a Tree control when dragging data from one Tree control to another,
* it prevents the drop.</p>
*
* @eventType mx.events.DragEvent.DRAG_COMPLETE
*/
<a href="Event%28name%3D%26quot%3BdragComplete%26quot%3B%2C%20type%3D%26quot%3Bmx.events.DragEvent%26quot%3B%29">Event(name="dragComplete", type="mx.events.DragEvent")</a>
//--------------------------------------
// State events
//--------------------------------------
/**
* Dispatched after the <code>currentState</code> property changes,
* but before the view state changes.
*
* @eventType mx.events.StateChangeEvent.CURRENT_STATE_CHANGING
*/
<a href="Event%28name%3D%26quot%3BcurrentStateChanging%26quot%3B%2C%20type%3D%26quot%3Bmx.events.StateChangeEvent%26quot%3B%29">Event(name="currentStateChanging", type="mx.events.StateChangeEvent")</a>
/**
* Dispatched after the view state has changed.
*
* @eventType mx.events.StateChangeEvent.CURRENT_STATE_CHANGE
*/
<a href="Event%28name%3D%26quot%3BcurrentStateChange%26quot%3B%2C%20type%3D%26quot%3Bmx.events.StateChangeEvent%26quot%3B%29">Event(name="currentStateChange", type="mx.events.StateChangeEvent")</a>
//--------------------------------------
// Tooltip events
//--------------------------------------
/**
* Dispatched by the component when it is time to create a ToolTip.
*
* <p>If you create your own IToolTip object and place a reference
* to it in the <code>toolTip</code> property of the event object
* that is passed to your <code>toolTipCreate</code> handler,
* the ToolTipManager displays your custom ToolTip.
* Otherwise, the ToolTipManager creates an instance of
* <code>ToolTipManager.toolTipClass</code> to display.</p>
*
* <p>The sequence of ToolTip events is <code>toolTipStart</code>,
* <code>toolTipCreate</code>, <code>toolTipShow</code>,
* <code>toolTipShown</code>, <code>toolTipHide</code>,
* and <code>toolTipEnd</code>.</p>
*
* @eventType mx.events.ToolTipEvent.TOOL_TIP_CREATE
*/
<a href="Event%28name%3D%26quot%3BtoolTipCreate%26quot%3B%2C%20type%3D%26quot%3Bmx.events.ToolTipEvent%26quot%3B%29">Event(name="toolTipCreate", type="mx.events.ToolTipEvent")</a>
/**
* Dispatched by the component when its ToolTip has been hidden
* and will be discarded soon.
*
* <p>If you specify an effect using the
* <code>ToolTipManager.hideEffect</code> property,
* this event is dispatched after the effect stops playing.</p>
*
* <p>The sequence of ToolTip events is <code>toolTipStart</code>,
* <code>toolTipCreate</code>, <code>toolTipShow</code>,
* <code>toolTipShown</code>, <code>toolTipHide</code>,
* and <code>toolTipEnd</code>.</p>
*
* @eventType mx.events.ToolTipEvent.TOOL_TIP_END
*/
<a href="Event%28name%3D%26quot%3BtoolTipEnd%26quot%3B%2C%20type%3D%26quot%3Bmx.events.ToolTipEvent%26quot%3B%29">Event(name="toolTipEnd", type="mx.events.ToolTipEvent")</a>
/**
* Dispatched by the component when its ToolTip is about to be hidden.
*
* <p>If you specify an effect using the
* <code>ToolTipManager.hideEffect</code> property,
* this event is dispatched before the effect starts playing.</p>
*
* <p>The sequence of ToolTip events is <code>toolTipStart</code>,
* <code>toolTipCreate</code>, <code>toolTipShow</code>,
* <code>toolTipShown</code>, <code>toolTipHide</code>,
* and <code>toolTipEnd</code>.</p>
*
* @eventType mx.events.ToolTipEvent.TOOL_TIP_HIDE
*/
<a href="Event%28name%3D%26quot%3BtoolTipHide%26quot%3B%2C%20type%3D%26quot%3Bmx.events.ToolTipEvent%26quot%3B%29">Event(name="toolTipHide", type="mx.events.ToolTipEvent")</a>
/**
* Dispatched by the component when its ToolTip is about to be shown.
*
* <p>If you specify an effect using the
* <code>ToolTipManager.showEffect</code> property,
* this event is dispatched before the effect starts playing.
* You can use this event to modify the ToolTip before it appears.</p>
*
* <p>The sequence of ToolTip events is <code>toolTipStart</code>,
* <code>toolTipCreate</code>, <code>toolTipShow</code>,
* <code>toolTipShown</code>, <code>toolTipHide</code>,
* and <code>toolTipEnd</code>.</p>
*
* @eventType mx.events.ToolTipEvent.TOOL_TIP_SHOW
*/
<a href="Event%28name%3D%26quot%3BtoolTipShow%26quot%3B%2C%20type%3D%26quot%3Bmx.events.ToolTipEvent%26quot%3B%29">Event(name="toolTipShow", type="mx.events.ToolTipEvent")</a>
/**
* Dispatched by the component when its ToolTip has been shown.
*
* <p>If you specify an effect using the
* <code>ToolTipManager.showEffect</code> property,
* this event is dispatched after the effect stops playing.</p>
*
* <p>The sequence of ToolTip events is <code>toolTipStart</code>,
* <code>toolTipCreate</code>, <code>toolTipShow</code>,
* <code>toolTipShown</code>, <code>toolTipHide</code>,
* and <code>toolTipEnd</code>.</p>
*
* @eventType mx.events.ToolTipEvent.TOOL_TIP_SHOWN
*/
<a href="Event%28name%3D%26quot%3BtoolTipShown%26quot%3B%2C%20type%3D%26quot%3Bmx.events.ToolTipEvent%26quot%3B%29">Event(name="toolTipShown", type="mx.events.ToolTipEvent")</a>
/**
* Dispatched by a component whose <code>toolTip</code> property is set,
* as soon as the user moves the mouse over it.
*
* <p>The sequence of ToolTip events is <code>toolTipStart</code>,
* <code>toolTipCreate</code>, <code>toolTipShow</code>,
* <code>toolTipShown</code>, <code>toolTipHide</code>,
* and <code>toolTipEnd</code>.</p>
*
* @eventType mx.events.ToolTipEvent.TOOL_TIP_START
*/
<a href="Event%28name%3D%26quot%3BtoolTipStart%26quot%3B%2C%20type%3D%26quot%3Bmx.events.ToolTipEvent%26quot%3B%29">Event(name="toolTipStart", type="mx.events.ToolTipEvent")</a>
<a href="DefaultProperty%28%26quot%3Bcontent%26quot%3B%29">DefaultProperty("content")</a>
class UIMovieClip extends MovieClip
implements IDeferredInstantiationUIComponent, IToolTipManagerClient, IFocusManagerComponent, IStateClient
{
// Properties and methods for the implemented interfaces are omitted for clarity
/**
* Name of the object to use as the bounding box.
*
* <p>The bounding box is an object that is used to determine
* the size of the content. The actual content can be larger or
* smaller than the bounding box, but Flex will use the size of the
* bounding box when laying out its contents. This object is optional.
* If omitted, the actual content size is used instead.</p>
*
* @default "boundingBox"
*/
public var boundingBoxName:String = "boundingBox";
/**
* The reported bounds of the content.
*
* <p>If a boundsProxy is used, this is the bounds of the proxy.
* If there is no boundsProxy, this is the size of the content itself.</p>
*
* @default "boundsProxy"
*/
protected function get bounds():Rectangle;
/**
* Notify our parent that our size has changed.
*
* <p>This method is called automatically whenever the
* contentBounds are changed, but should be called directly
* if any other changes that affect the layout size or position
* of the component have changed.</p>
*/
protected function notifySizeChanged():void;
/**
* <p>Called for every frame. This method is responsible for
* tracking changes to size, and for running transitions.
* You can override this method if you need to do additional
* processing on every frame, but you should always call the
* super method first.</p>
*/
protected function enterFrameHandler(event:Event):void;
}
<a href="DefaultProperty%28%26quot%3Bcontent%26quot%3B%29">DefaultProperty("content")</a>
public class ContentMovieClip extends UIMovieClip
{
/**
* The flex content to display inside this container.
* The component must have a FlexContentHolder symbol
* as a child. The FlexContentHolder symbol becomes the
* parent of the Flex content.
*
* @default null
*/
public var content:IUIComponent;
}
UIMovieClip integrates with numerous Flex features including Containers, LayoutManager, FocusManager, ToolTipManager, skins, skin states, etc. All integration is transparent, and does not require any changes to the core Flex features.