blob: dbc50fe9c8212a1bf67120b6258da6376ec7d23c [file] [log] [blame]
////////////////////////////////////////////////////////////////////////////////
//
// 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.managers.systemClasses
{
import flash.display.DisplayObject;
import flash.display.DisplayObjectContainer;
import flash.display.InteractiveObject;
import flash.events.IEventDispatcher;
import mx.core.IFlexDisplayObject;
import mx.core.IFlexModule;
import mx.core.IFlexModuleFactory;
import mx.core.IFontContextComponent;
import mx.core.IInvalidating;
import mx.core.IUIComponent;
import mx.core.UIComponent;
import mx.core.mx_internal;
import mx.events.FlexEvent;
import mx.managers.ILayoutManagerClient;
import mx.managers.ISystemManager;
import mx.managers.ISystemManagerChildManager;
import mx.managers.SystemManager;
import mx.messaging.config.LoaderConfig;
import mx.preloaders.Preloader;
import mx.styles.ISimpleStyleClient;
import mx.styles.IStyleClient;
import mx.utils.LoaderUtil;
use namespace mx_internal;
[ExcludeClass]
public class ChildManager implements ISystemManagerChildManager
{
include "../../core/Version.as";
//--------------------------------------------------------------------------
//
// Constructor
//
//--------------------------------------------------------------------------
/**
* Constructor.
*
* <p>This is the starting point for all Flex applications.
* This class is set to be the root class of a Flex SWF file.
* Flash Player instantiates an instance of this class,
* causing this constructor to be called.</p>
*/
public function ChildManager(systemManager:IFlexModuleFactory)
{
super();
if (systemManager is ISystemManager)
{
systemManager["childManager"] = this;
this.systemManager = ISystemManager(systemManager);
this.systemManager.registerImplementation("mx.managers::ISystemManagerChildManager", this);
}
}
//--------------------------------------------------------------------------
//
// Variables
//
//--------------------------------------------------------------------------
/**
* @private
*/
private var systemManager:ISystemManager;
//--------------------------------------------------------------------------
//
// Methods: Child management
//
//--------------------------------------------------------------------------
/**
* @private
*/
public function addingChild(child:DisplayObject):void
{
var newNestLevel:int = 1;
// non-top level system managers may not be able to reference their parent if
// they are a proxy for popups.
if (!topLevel && DisplayObject(systemManager).parent)
{
// non-topLevel SystemManagers are buried by Flash.display.Loader and
// other non-framework layers so we have to figure out the nestlevel
// by searching up the parent chain.
var obj:DisplayObjectContainer = DisplayObject(systemManager).parent.parent;
while (obj)
{
if (obj is ILayoutManagerClient)
{
newNestLevel = ILayoutManagerClient(obj).nestLevel + 1;
break;
}
obj = obj.parent;
}
}
nestLevel = newNestLevel;
if (child is IUIComponent)
IUIComponent(child).systemManager = systemManager;
// 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 (child is IUIComponent &&
!IUIComponent(child).document)
{
IUIComponent(child).document = systemManager.document;
}
// Set the moduleFactory to the child, but don't overwrite an existing moduleFactory.
if (child is IFlexModule && IFlexModule(child).moduleFactory == null)
IFlexModule(child).moduleFactory = systemManager;
// Set the font context in non-UIComponent children.
// UIComponent children use moduleFactory.
if (child is IFontContextComponent && !child is UIComponent &&
IFontContextComponent(child).fontContext == null)
IFontContextComponent(child).fontContext = systemManager;
// 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.
if (child is ILayoutManagerClient)
ILayoutManagerClient(child).nestLevel = nestLevel + 1;
if (child is InteractiveObject)
if (InteractiveObject(systemManager).doubleClickEnabled)
InteractiveObject(child).doubleClickEnabled = true;
if (child is IUIComponent)
IUIComponent(child).parentChanged(DisplayObjectContainer(systemManager));
// 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 (child is IStyleClient)
IStyleClient(child).regenerateStyleCache(true);
if (child is ISimpleStyleClient)
ISimpleStyleClient(child).styleChanged(null);
if (child is IStyleClient)
IStyleClient(child).notifyStyleChangeInChildren(null, true);
// Need to check to see if the child is an UIComponent
// without actually linking in the UIComponent class.
if (child is UIComponent)
UIComponent(child).initThemeColor();
// 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.
if (child is UIComponent)
UIComponent(child).stylesInitialized();
}
/**
* @private
*/
public function childAdded(child:DisplayObject):void
{
if (child.hasEventListener(FlexEvent.ADD))
child.dispatchEvent(new FlexEvent(FlexEvent.ADD));
if (child is IUIComponent)
IUIComponent(child).initialize(); // calls child.createChildren()
}
/**
* @private
*/
public function removingChild(child:DisplayObject):void
{
if (child.hasEventListener(FlexEvent.REMOVE))
child.dispatchEvent(new FlexEvent(FlexEvent.REMOVE));
}
/**
* @private
*/
public function childRemoved(child:DisplayObject):void
{
if (child is IUIComponent)
IUIComponent(child).parentChanged(null);
}
//--------------------------------------------------------------------------
//
// Methods: Styles
//
//--------------------------------------------------------------------------
/**
* @private
* Call regenerateStyleCache() on all children of this SystemManager.
* If the recursive parameter is true, continue doing this
* for all descendants of these children.
*/
public function regenerateStyleCache(recursive:Boolean):void
{
var foundTopLevelWindow:Boolean = false;
var n:int = systemManager.rawChildren.numChildren;
for (var i:int = 0; i < n; i++)
{
var child:IStyleClient =
systemManager.rawChildren.getChildAt(i) as IStyleClient;
if (child)
child.regenerateStyleCache(recursive);
if (isTopLevelWindow(DisplayObject(child)))
foundTopLevelWindow = true;
// Refetch numChildren because notifyStyleChangedInChildren()
// can add/delete a child and therefore change numChildren.
n = systemManager.rawChildren.numChildren;
}
// During startup the top level window isn't added
// to the child list until late into the startup sequence.
// Make sure we call regenerateStyleCache()
// on the top level window even if it isn't a child yet.
if (!foundTopLevelWindow && topLevelWindow is IStyleClient)
IStyleClient(topLevelWindow).regenerateStyleCache(recursive);
}
/**
* @private
* Call styleChanged() and notifyStyleChangeInChildren()
* on all children of this SystemManager.
* If the recursive parameter is true, continue doing this
* for all descendants of these children.
*/
public function notifyStyleChangeInChildren(styleProp:String,
recursive:Boolean):void
{
var foundTopLevelWindow:Boolean = false;
var n:int = systemManager.rawChildren.numChildren;
for (var i:int = 0; i < n; i++)
{
var child:IStyleClient =
systemManager.rawChildren.getChildAt(i) as IStyleClient;
if (child)
{
child.styleChanged(styleProp);
child.notifyStyleChangeInChildren(styleProp, recursive);
}
if (isTopLevelWindow(DisplayObject(child)))
foundTopLevelWindow = true;
// Refetch numChildren because notifyStyleChangedInChildren()
// can add/delete a child and therefore change numChildren.
n = systemManager.rawChildren.numChildren;
}
// During startup the top level window isn't added
// to the child list until late into the startup sequence.
// Make sure we call notifyStyleChangeInChildren()
// on the top level window even if it isn't a child yet.
if (!foundTopLevelWindow && topLevelWindow is IStyleClient)
{
IStyleClient(topLevelWindow).styleChanged(styleProp);
IStyleClient(topLevelWindow).notifyStyleChangeInChildren(
styleProp, recursive);
}
}
/**
* @private
* Instantiates an instance of the top level window
* and adds it as a child of the SystemManager.
*/
public function initializeTopLevelWindow(width:Number, height:Number):void
{
CONFIG::performanceInstrumentation
{
var perfUtil:mx.utils.PerfUtil = mx.utils.PerfUtil.getInstance();
perfUtil.markTime("ChildManager.initializeTopLevelWindow().start");
perfUtil.markTime("SystemManager.create().start");
}
var app:IUIComponent;
// Create a new instance of the toplevel class
systemManager.document = app = topLevelWindow = IUIComponent(systemManager.create());
CONFIG::performanceInstrumentation
{
perfUtil.markTime("SystemManager.create().end");
}
if (systemManager.document)
{
// Add listener for the creationComplete event
IEventDispatcher(app).addEventListener(FlexEvent.CREATION_COMPLETE,
appCreationCompleteHandler);
// if somebody has set this in our applicationdomain hierarchy, don't overwrite it
if (!LoaderConfig._url)
{
LoaderConfig._url = LoaderUtil.normalizeURL(systemManager.loaderInfo);
LoaderConfig._parameters = systemManager.loaderInfo.parameters;
LoaderConfig._swfVersion = systemManager.loaderInfo.swfVersion;
}
IFlexDisplayObject(app).setActualSize(width, height);
// Wait for the app to finish its initialization sequence
// before doing an addChild().
// Otherwise, the measurement/layout code will cause the
// player to do a bunch of unnecessary screen repaints,
// which slows application startup time.
// Pass the application instance to the preloader.
// Note: preloader can be null when the user chooses
// Control > Play in the standalone player.
if (preloader)
preloader.registerApplication(app);
// The Application doesn't get added to the SystemManager in the standard way.
// We want to recursively create the entire application subtree and process
// it with the LayoutManager before putting the Application on the display list.
// So here we what would normally happen inside an override of addChild().
// Leter, when we actually attach the Application instance,
// we call super.addChild(), which is the bare player method.
addingChild(DisplayObject(app));
CONFIG::performanceInstrumentation
{
perfUtil.markTime("Application.createChildren().start");
}
childAdded(DisplayObject(app)); // calls app.createChildren()
CONFIG::performanceInstrumentation
{
perfUtil.markTime("Application.createChildren().end");
}
}
else
{
systemManager.document = this;
}
CONFIG::performanceInstrumentation
{
perfUtil.markTime("ChildManager.initializeTopLevelWindow().end");
}
}
/**
* Override this function if you want to perform any logic
* when the application has finished initializing itself.
*/
private function appCreationCompleteHandler(event:FlexEvent):void
{
if (!topLevel && DisplayObject(systemManager).parent)
{
var obj:DisplayObjectContainer = DisplayObject(systemManager).parent.parent;
while (obj)
{
if (obj is IInvalidating)
{
IInvalidating(obj).invalidateSize();
IInvalidating(obj).invalidateDisplayList();
return;
}
obj = obj.parent;
}
}
}
//--------------------------------------------------------------------------
//
// Methods to implement SystemManager methods
//
// systemManager may be a SystemManager or WindowedSystemManager
// so we use the array access operertor to get at the methods/properties.
//
//--------------------------------------------------------------------------
private function isTopLevelWindow(object:DisplayObject):Boolean
{
return systemManager["isTopLevelWindow"](object);
}
private function get topLevel():Boolean
{
return systemManager["topLevel"];
}
private function set topLevel(topLevel:Boolean):void
{
systemManager["topLevel"] = topLevel;
}
private function get topLevelWindow():IUIComponent
{
return systemManager["topLevelWindow"];
}
private function set topLevelWindow(window:IUIComponent):void
{
systemManager["topLevelWindow"] = window;
}
private function get nestLevel():int
{
return systemManager["nestLevel"];
}
private function set nestLevel(level:int):void
{
systemManager["nestLevel"] = level;
}
private function get preloader():Preloader
{
return systemManager["preloader"];
}
private function set preloader(preloader:Preloader):void
{
systemManager["preloader"] = preloader;
}
}
}