//////////////////////////////////////////////////////////////////////////////// // // 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.

* * @param newWidth The new width for this object. * * @param newHeight The new height for this object. * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ override public function setActualSize(newWidth:Number, newHeight:Number):void { if (sizeChanged(_width, newWidth) || sizeChanged(_height, newHeight)) dispatchResizeEvent(); // Remember our new actual size so we can report it later in the // width/height getters. _width = newWidth; _height = newHeight; if (flexContent) { sizeFlexContent(); } } //-------------------------------------------------------------------------- // // Layout methods // //-------------------------------------------------------------------------- /** * Notify parent that the size of this object has changed. * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ override protected function notifySizeChanged():void { super.notifySizeChanged(); sizeFlexContent(); } //-------------------------------------------------------------------------- // // Flex content methods // //-------------------------------------------------------------------------- /** * Utility function that prepares Flex content to be used as a child of * this component. * Set the 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); } } }