//////////////////////////////////////////////////////////////////////////////// // // 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.events.Event; import flash.utils.getDefinitionByName; import mx.core.IFlexModule; import mx.core.IUIComponent; import mx.core.mx_internal; use namespace mx_internal; [ExcludeClass] /** * The FlexContentHolder class is for internal use only. * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public dynamic class FlexContentHolder extends ContainerMovieClip { //-------------------------------------------------------------------------- // // Constructor // //-------------------------------------------------------------------------- /** * Constructor. * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function FlexContentHolder() { super(); showInAutomationHierarchy = false; // grab our width and height before setting scaleX=scaleY=1 _width = this.width; _height = this.height; // set scaleX, scaleY to 1 in case the user scaled the // FlexContentHolder when creating this ContainerMovieClip. // If we don't set scale here, then the content in the container // would be scaled as well $scaleX = $scaleY = 1; removeEventListener(Event.ADDED, addedHandler); removeEventListener(Event.REMOVED, removedHandler); } //-------------------------------------------------------------------------- // // Internal variables // //-------------------------------------------------------------------------- private var flexContent:IUIComponent; // The Flex content private var pendingFlexContent:IUIComponent; // Only used if flexContent is set early //-------------------------------------------------------------------------- // // Private Properties // //-------------------------------------------------------------------------- /** * @private * The FlexContentHolder symbol that a user drags out on to the screen in * Flash Authoring to let us know where the Flash content goes. This symbol is * actually a child of us (the FlashContentHolder, which is the actual object they * are dragging out). We modify the scale and alpha of this object to get sizing * correct and to make sure this object doesn't actually show up in the Flex project. */ private function get flexContentHolderSymbol():DisplayObject { return getChildAt(0); } //-------------------------------------------------------------------------- // // Properties // //-------------------------------------------------------------------------- //---------------------------------- // content //---------------------------------- /** * @inheritDoc * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ override public function get content():IUIComponent { return flexContent; } override public function set content(value:IUIComponent):void { if (initialized) setFlexContent(value); else pendingFlexContent = value; } //-------------------------------------------------------------------------- // // IUIComponent methods // //-------------------------------------------------------------------------- /** * Initialize the object. * * @see mx.core.UIComponent#initialize() * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ override public function initialize():void { super.initialize(); // initialize is only called when we are running in Flex. // Since we are in Flex, let's hide the content placeholder. // Rather than removing it (which can cause problems with // sizing), we set the alpha to 0. flexContentHolderSymbol.alpha = 0; // See if we have any pending flex content if (pendingFlexContent) { setFlexContent(pendingFlexContent); pendingFlexContent = null; } } //-------------------------------------------------------------------------- // // IFlexDisplayObject methods // //-------------------------------------------------------------------------- /** * Sets the actual size of this object. * *
This method is mainly for use in implementing the
* updateDisplayList()
method, which is where
* this object's actual size is computed based on
* its explicit size, parent-relative (percent) size,
* and measured size.
* Apply this actual size to the object
* by calling the setActualSize()
method.
In other situations, you should be setting properties
* such as width
, height
,
* percentWidth
, or percentHeight
* rather than calling this method.
content
property rather than calling
* this method directly.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected function setFlexContent(value:IUIComponent):void
{
// Remove any existing content
if (flexContent)
{
removeChild(DisplayObject(flexContent));
flexContent = null;
}
// Add the new content
flexContent = value;
if (flexContent)
{
addChild(DisplayObject(flexContent));
var uiComponentClass:Class;
// Dynamically load the UIComponent class, but don't fail on error.
// This allows us to work in Flex (where UIComponent is defined), and
// in Flash (where it UIComponent is not defined).
try
{
uiComponentClass = Class(getDefinitionByName("mx.core::UIComponent"));
}
catch (e:Error)
{
}
// Do the Flex initialization
if (uiComponentClass)
{
// Find our parent UIComponent
var uicParent:Object;
var p:DisplayObjectContainer = parent;
while (p)
{
if (p is uiComponentClass)
{
uicParent = p;
break;
}
p = p.parent;
}
if (!uicParent)
{
try
{
var applicationClass:Class = Class(getDefinitionByName("mx.core::ApplicationGlobals"));
uicParent = applicationClass.application;
}
catch (e:Error)
{
}
}
if (!uicParent)
return;
// The rest of this was copied from UIComponent.addingChild()...
// If the document property isn't already set on the child,
// set it to be the same as this component's document.
// The document setter will recursively set it on any
// descendants of the child that exist.
if (!flexContent.document)
{
flexContent.document = uicParent.document;
}
if (flexContent is InteractiveObject)
if (doubleClickEnabled)
InteractiveObject(flexContent).doubleClickEnabled = true;
// Propagate moduleFactory to the child, but don't overwrite an existing moduleFactory.
if (flexContent is IFlexModule && IFlexModule(flexContent).moduleFactory == null)
{
if (uicParent is IFlexModule && IFlexModule(uicParent).moduleFactory != null)
IFlexModule(flexContent).moduleFactory = IFlexModule(uicParent).moduleFactory;
else if (document is IFlexModule && uicParent.document.moduleFactory != null)
IFlexModule(flexContent).moduleFactory = uicParent.document.moduleFactory;
else if (uicParent is IFlexModule && IFlexModule(uicParent).moduleFactory != null)
IFlexModule(flexContent).moduleFactory = IFlexModule(uicParent).moduleFactory;
}
// Sets up the inheritingStyles and nonInheritingStyles objects
// and their proto chains so that getStyle() works.
// If this object already has some children,
// then reinitialize the children's proto chains.
if (flexContent is uiComponentClass)
{
var child:Object = flexContent;
// set the child's parent to this for now (when initializing styles,
// we'll have to do some funky business).
child._parent = this;
// Set the nestLevel of the child to be one greater
// than the nestLevel of this component.
// The nestLevel setter will recursively set it on any
// descendants of the child that exist.
child.nestLevel = uicParent.nestLevel + 1;
// Temporarily set the _parent property of the child to the nearest UIComponent
// parent. This allows inheriting styles to be picked up correctly.
child._parent = uicParent;
child.regenerateStyleCache(true);
child.styleChanged(null);
child.notifyStyleChangeInChildren(null, true);
child.initThemeColor();
// Reset the _parent property.
child._parent = this;
// Inform the component that it's style properties
// have been fully initialized. Most components won't care,
// but some need to react to even this early change.
child.stylesInitialized();
}
flexContent.initialize();
}
}
}
/**
* @private
*/
public function sizeFlexContent():void
{
if (!flexContent)
return;
var myParent:ContainerMovieClip = ContainerMovieClip(parent);
var contentWidth:Number;
var contentHeight:Number;
var containerWidth:Number = _width;
var containerHeight:Number = _height;
// width and height are what we actually want our content
// to fill up, but it doesn't take in to account our secretScale.
if (!myParent.scaleContentWhenResized && myParent._layoutFeatures != null)
{
// apply the scale to the width/height
containerWidth *= myParent._layoutFeatures.stretchX;
containerHeight *= myParent._layoutFeatures.stretchY;
// also need to scale our placeholder so the bounds are correct
// Example: object is naturally 100x100 but width=50, height=50
// ContainerMovieClip is scaled to .5
// However, the FlexContentHolder is scaled to 2 if scaleContentWhenResized == false
// to counteract this scale.
// In order for the FlexContentHolderSymbol to not extend outside of these bounds, we
// also scale that down to .5
flexContentHolderSymbol.scaleX = myParent._layoutFeatures.stretchX;
flexContentHolderSymbol.scaleY = myParent._layoutFeatures.stretchY;
}
else
{
// reset the FlexContentHolderSymbol's scale to 1 (see comment above where we set
// it to stretchX/stretchY from our parent)
flexContentHolderSymbol.scaleX = 1;
flexContentHolderSymbol.scaleY = 1;
}
// Size the flex content to what they want to be,
// making sure we size them to their minimum size and
// making sure we fit within this container.
// We don't do anything too fancy here for layout, try percent
// widths and heights and make sure
// our size is large enough to hold our content in the first place
if (!isNaN(content.percentWidth))
contentWidth = containerWidth * Math.min(content.percentWidth * .01, 1);
else
contentWidth = Math.min(containerWidth, flexContent.getExplicitOrMeasuredWidth());
// above: should we size to explicWidth if it's larger than containerWidth? Or should we do the min here?
if (!isNaN(content.percentHeight))
contentHeight = containerHeight * Math.min(content.percentHeight * .01, 1);
else
contentHeight = Math.min(containerHeight, flexContent.getExplicitOrMeasuredHeight());
contentWidth = Math.max(flexContent.minWidth, contentWidth);
contentHeight = Math.max(flexContent.minHeight, contentHeight);
contentWidth = Math.min(flexContent.maxWidth, contentWidth);
contentHeight = Math.min(flexContent.maxHeight, contentHeight);
flexContent.setActualSize(contentWidth, contentHeight);
}
}
}