| //////////////////////////////////////////////////////////////////////////////// |
| // |
| // 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. |
| * |
| * <p>This method is mainly for use in implementing the |
| * <code>updateDisplayList()</code> 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 <code>setActualSize()</code> method.</p> |
| * |
| * <p>In other situations, you should be setting properties |
| * such as <code>width</code>, <code>height</code>, |
| * <code>percentWidth</code>, or <code>percentHeight</code> |
| * rather than calling this method.</p> |
| * |
| * @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 <code>content</code> 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); |
| } |
| } |
| } |