////////////////////////////////////////////////////////////////////////////////
//
//  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 spark.components
{

import flash.display.DisplayObject;
import flash.display.InteractiveObject;
import flash.display.StageDisplayState;
import flash.events.ContextMenuEvent;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.FullScreenEvent;
import flash.events.SoftKeyboardEvent;
import flash.events.UncaughtErrorEvent;
import flash.external.ExternalInterface;
import flash.geom.Rectangle;
import flash.net.URLRequest;
import flash.net.navigateToURL;
import flash.system.Capabilities;
import flash.ui.ContextMenu;
import flash.ui.ContextMenuItem;
import flash.utils.Dictionary;
import flash.utils.setInterval;

import mx.core.EventPriority;
import mx.core.FlexGlobals;
import mx.core.IInvalidating;
import mx.core.InteractionMode;
import mx.core.Singleton;
import mx.core.UIComponentGlobals;
import mx.core.mx_internal;
import mx.managers.FocusManager;
import mx.managers.IActiveWindowManager;
import mx.managers.ILayoutManager;
import mx.managers.ISystemManager;
import mx.managers.SystemManager;
import mx.managers.ToolTipManager;
import mx.utils.BitFlagUtil;
import mx.utils.DensityUtil;
import mx.utils.LoaderUtil;
import mx.utils.Platform;

import spark.layouts.supportClasses.LayoutBase;

use namespace mx_internal;

//--------------------------------------
//  Events
//--------------------------------------

/**
 *  Dispatched after the Application has been initialized,
 *  processed by the LayoutManager, and attached to the display list.
 *
 *  @eventType mx.events.FlexEvent.APPLICATION_COMPLETE
 *
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 1.5
 *  @productversion Flex 4
 */
[Event(name="applicationComplete", type="mx.events.FlexEvent")]

/**
 *  Dispatched when an HTTPService call fails.
 *
 *  @eventType flash.events.ErrorEvent.ERROR
 *
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 1.5
 *  @productversion Flex 4
 */
[Event(name="error", type="flash.events.ErrorEvent")]

/**
 *  Dispatched when an uncaught error is caught by the Global Exception Handler
 *
 *  @eventType flash.events.UncaughtErrorEvent.UNCAUGHT_ERROR
 *
 *  @langversion 3.0
 *  @playerversion Flash 10.1
 *  @playerversion AIR 2.0
 *  @productversion Flex 4.5
 */
[Event(name="uncaughtError", type="flash.events.UncaughtErrorEvent")]

//--------------------------------------
//  Styles
//--------------------------------------

/**
 *  The background color of the application. This color is used as the stage color for the
 *  application and the background color for the HTML embed tag.
 *
 *  @default 0x464646
 *
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 1.5
 *  @productversion Flex 4
 */
[Style(name="backgroundColor", type="uint", format="Color", inherit="no")]


/**
 * Height in pixels left for os top status bar display.
 * <p>Status bar height is set by default to 20 pixels (at 160 DPI) for iOS7, on the following default skins: </p>
 * <ul>
 *     <li>>skins.spark.ApplicationSkin</li>
 *     <li>spark.skins.mobile.TabbedViewNavigatorApplicationSkin</li>
 *     <li>spark.skins.mobile.ViewNavigatorApplicationSkin</li>
 *   </ul>
 */
[Style(name="osStatusBarHeight", type="Number", format="Length", inherit="no", theme="mobile")]

//--------------------------------------
//  Excluded APIs
//--------------------------------------

[Exclude(name="direction", kind="property")]
[Exclude(name="tabIndex", kind="property")]
[Exclude(name="toolTip", kind="property")]
[Exclude(name="x", kind="property")]
[Exclude(name="y", kind="property")]

//--------------------------------------
//  Other metadata
//--------------------------------------

/**
 *  The frameworks must be initialized by SystemManager.
 *  This factoryClass will be automatically subclassed by any
 *  MXML applications that don't explicitly specify a different
 *  factoryClass.
 *
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 1.5
 *  @productversion Flex 4
 */
[Frame(factoryClass="mx.managers.SystemManager")]

[ResourceBundle("components")]

/**
 *  Flex defines a default, or Application, container that lets you start
 *  adding content to your application without explicitly defining
 *  another container.
 *
 *  <p>The Application container has the following default characteristics:</p>
 *     <table class="innertable">
 *        <tr>
 *           <th>Characteristic</th>
 *           <th>Description</th>
 *        </tr>
 *        <tr>
 *           <td>Default size</td>
 *           <td>375 pixels high and 500 pixels wide in the Standalone Flash Player,
 *               and all available space in a browser</td>
 *        </tr>
 *        <tr>
 *           <td>Minimum size</td>
 *           <td>0 pixels wide and 0 pixels high</td>
 *        </tr>
 *        <tr>
 *           <td>Maximum size</td>
 *           <td>No limit</td>
 *        </tr>
 *        <tr>
 *           <td>Default skin class</td>
 *           <td>spark.skins.spark.ApplicationSkin</td>
 *        </tr>
 *     </table>
 *
 *  @mxml
 *
 *  <p>The <code>&lt;s:Application&gt;</code> tag inherits all of the tag
 *  attributes of its superclass and adds the following tag attributes:</p>
 *
 *  <pre>
 *  &lt;s:Application
 *    <strong>Properties</strong>
 *    applicationDPI=<i>Device dependent</i>"
 *    backgroundColor="0xFFFFFF"
 *    colorCorrection="default"
 *    controlBarContent="null"
 *    controlBarLayout="HorizontalLayout"
 *    controlBarVisible="true"
 *    frameRate="24"
 *    pageTitle""
 *    preloader="<i>No default</i>"
 *    preloaderChromeColor="<i>No default</i>"
 *    resizeForSoftKeyboard=true"
 *    runtimeDPIProvider="RuntimeDPIProvider"
 *    scriptRecursionLimit="1000"
 *    scriptTimeLimit="60"
 *    splashScreenImage=""
 *    splashScreenMinimumDisplayTime="1000"
 *    splashScreenScaleMode="none"
 *    usePreloader="true"
 *    viewSourceURL=""
 *    xmlns:<i>No default</i>="<i>No default</i>"
 *
 *    <strong>Events</strong>
 *    applicationComplete="<i>No default</i>"
 *    error="<i>No default</i>"
 *  /&gt;
 *  </pre>
 *
 *  @see spark.skins.spark.ApplicationSkin
 *  @includeExample examples/ApplicationContainerExample.mxml
 *
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 1.5
 *  @productversion Flex 4
 */
public class Application extends SkinnableContainer
{
    include "../core/Version.as";

    //--------------------------------------------------------------------------
    //
    //  Class constants
    //
    //--------------------------------------------------------------------------

    /**
     *  @private
     */
    private static const CONTROLBAR_PROPERTY_FLAG:uint = 1 << 0;

    /**
     *  @private
     */
    private static const LAYOUT_PROPERTY_FLAG:uint = 1 << 1;

    /**
     *  @private
     */
    private static const VISIBLE_PROPERTY_FLAG:uint = 1 << 2;

    //--------------------------------------------------------------------------
    //
    //  Class properties
    //
    //--------------------------------------------------------------------------

    //--------------------------------------------------------------------------
    //
    //  Constructor
    //
    //--------------------------------------------------------------------------

    /**
     *  Constructor.
     *
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public function Application()
    {
        UIComponentGlobals.layoutManager = ILayoutManager(
            Singleton.getInstance("mx.managers::ILayoutManager"));
        UIComponentGlobals.layoutManager.usePhasedInstantiation = true;

        if (!FlexGlobals.topLevelApplication)
            FlexGlobals.topLevelApplication = this;

        super();

        showInAutomationHierarchy = true;

        initResizeBehavior();
    }

    //--------------------------------------------------------------------------
    //
    //  Variables
    //
    //--------------------------------------------------------------------------
    
    /**
     *  @private
     *  Variable that determines whether this application is running on iOS.
     */
    private var isIOS:Boolean = false;
    
    /**
     *  @private
     *  This variable stores the last object that received the SOFT_KEYBOARD_ACTIVATE
     *  event.
     */
    private var softKeyboardTarget:Object = null;
    
    /**
     *  @private
     *  Flag set to true if the application has temporarily set its explicit
     *  width and height to deal with orientation.
     */ 
    private var explicitSizingForOrientation:Boolean = false;
    
    /**
     *  @private
     *  Caches the application's width and height values for better resizing
     *  of the screen during orientation changes. Keys are composed of the width and
     *  height values in a string of the form "w:h", e.g. "1004:768" and represent
     *  the screen dimensions before the orientation change. Values are
     *  objects containing width and height properties that represent the screen dimensions
     *  after the orientation change.
     */
    private var cachedDimensions:Dictionary;
    
    /**
     *  @private
     *  Previous width of the application prior to an orientation change 
     */    
    private var previousWidth:Number;
    
    /**
     *  @private
     *  Previous height of the application prior to an orientation change 
     */    
    private var previousHeight:Number;
    
    /**
     *  @private
     *  Flag to determine if the keyboard is active during an orientation change,
     *  to minimize renders during the orientation change.
     */
    private var keyboardActiveInOrientationChange:Boolean = false;
    
    /**
     *  @private
     */
    private var resizeHandlerAdded:Boolean = false;

    /**
     *  @private
     */
    private var percentBoundsChanged:Boolean;

    /**
     *  @private
     *  Placeholder for Preloader object reference.
     */
    private var preloadObj:Object;

    /**
     *  @private
     *  This flag indicates whether the width of the Application instance
     *  can change or has been explicitly set by the developer.
     *  When the stage is resized we use this flag to know whether the
     *  width of the Application should be modified.
     */
    private var resizeWidth:Boolean = true;

    /**
     *  @private
     *  This flag indicates whether the height of the Application instance
     *  can change or has been explicitly set by the developer.
     *  When the stage is resized we use this flag to know whether the
     *  height of the Application should be modified.
     */
    private var resizeHeight:Boolean = true;
    
    /**
     *  @private
     */
    private static var _softKeyboardBehavior:String = null;

    /**
     *  @private
     */
    mx_internal var isSoftKeyboardActive:Boolean = false;
    
    /**
     *  @private
     */
    private var synchronousResize:Boolean = false;

    /**
     * @private
     * (Possibly null) reference to the View Source context menu item,
     * so that we can update it for runtime localization.
     */
    private var viewSourceCMI:ContextMenuItem;

    /**
     * @private 
     * Return the density scaling factor for the application 
     */    
    private function get scaleFactor():Number
    {
        if (systemManager)
            return (systemManager as SystemManager).densityScale;

        return 1;
    }
    
    //----------------------------------
    //  colorCorrection
    //----------------------------------

    [Inspectable(enumeration="default,off,on", defaultValue="default" )]

   /**
    *  The value of the stage's <code>colorCorrection</code> property.
    *  If this application does not have access to the stage's <code>colorCorrection</code> property,
    *  the value of the <code>colorCorrection</code> property is <code>null</code>.
    *
    *  <p>Only the main application is allowed to set the <code>colorCorrection</code>
    *  property. If a nested application's needs to set the color correction property, it
    *  must set it by referencing the main application's instance.</p>
    *
    *  @default ColorCorrection.DEFAULT
    *
    *  @see flash.display.ColorCorrection
    *
    *  @langversion 3.0
    *  @playerversion Flash 10
    *  @playerversion AIR 1.5
    *  @productversion Flex 4
    */
    public function get colorCorrection():String
    {
        try
        {
            var sm:ISystemManager = systemManager;
            if (sm && sm.stage)
                return sm.stage.colorCorrection;
        }
        catch (e:SecurityError)
        {
            // ignore error if this application is not allow
            // to view the colorCorrection property.
        }

        return null;
    }

    /**
     * @private
     */
    public function set colorCorrection(value:String):void
    {
        // Since only the main application is allowed to change the value this property, there
        // is no need to catch security violations like in the getter.
        var sm:ISystemManager = systemManager;
        if (sm && sm.stage && sm.isTopLevelRoot())
            sm.stage.colorCorrection = value;
    }

    /**
     *  @private
     *  Several properties are proxied to controlBarGroup.  However, when controlBarGroup
     *  is not around, we need to store values set on SkinnableContainer.  This object
     *  stores those values.  If controlBarGroup is around, the values are stored
     *  on the controlBarGroup directly.  However, we need to know what values
     *  have been set by the developer on the SkinnableContainer (versus set on
     *  the controlBarGroup or defaults of the controlBarGroup) as those are values
     *  we want to carry around if the controlBarGroup changes (via a new skin).
     *  In order to store this info effeciently, controlBarGroupProperties becomes
     *  a uint to store a series of BitFlags.  These bits represent whether a
     *  property has been explicitely set on this SkinnableContainer.  When the
     *  controlBarGroup is not around, controlBarGroupProperties is a typeless
     *  object to store these proxied properties.  When controlBarGroup is around,
     *  controlBarGroupProperties stores booleans as to whether these properties
     *  have been explicitely set or not.
     */
    private var controlBarGroupProperties:Object = { visible: true };

    //----------------------------------
    //  controlBarGroup
    //----------------------------------

    [SkinPart(required="false")]

    /**
     *  The skin part that defines the appearance of the
     *  control bar area of the container.
     *  By default, the ApplicationSkin class defines the control bar area to appear at the top
     *  of the content area of the Application container with a grey background.
     *
     *  @see spark.skins.spark.ApplicationSkin
     *
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public var controlBarGroup:Group;

    //----------------------------------
    //  controlBarContent
    //----------------------------------

    [ArrayElementType("mx.core.IVisualElement")]

    /**
     *  The set of components to include in the control bar area of the
     *  Application container.
     *  The location and appearance of the control bar area of the Application container
     *  is determined by the spark.skins.spark.ApplicationSkin class.
     *  By default, the ApplicationSkin class defines the control bar area to appear at the top
     *  of the content area of the Application container with a grey background.
     *  Create a custom skin to change the default appearance of the control bar.
     *
     *  @default null
     *
     *  @see spark.skins.spark.ApplicationSkin
     *
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public function get controlBarContent():Array
    {
        if (controlBarGroup)
            return controlBarGroup.getMXMLContent();
        else
            return controlBarGroupProperties.controlBarContent;
    }

    /**
     *  @private
     */
    public function set controlBarContent(value:Array):void
    {
        if (controlBarGroup)
        {
            controlBarGroup.mxmlContent = value;
            controlBarGroupProperties = BitFlagUtil.update(controlBarGroupProperties as uint,
                                                        CONTROLBAR_PROPERTY_FLAG, value != null);
        }
        else
            controlBarGroupProperties.controlBarContent = value;

        invalidateSkinState();
    }

    //----------------------------------
    //  controlBarLayout
    //----------------------------------

    /**
     *  Defines the layout of the control bar area of the container.
     *
     *  @default HorizontalLayout
     *
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public function get controlBarLayout():LayoutBase
    {
        return (controlBarGroup)
            ? controlBarGroup.layout
            : controlBarGroupProperties.layout;
    }

    public function set controlBarLayout(value:LayoutBase):void
    {
        if (controlBarGroup)
        {
            controlBarGroup.layout = value;
            controlBarGroupProperties = BitFlagUtil.update(controlBarGroupProperties as uint,
                                                        LAYOUT_PROPERTY_FLAG, true);
        }
        else
            controlBarGroupProperties.layout = value;
    }

    //----------------------------------
    //  controlBarVisible
    //----------------------------------

    /**
     *  If <code>true</code>, the control bar is visible.
     *  The flag has no affect if there is no value set for
     *  the <code>controlBarContent</code> property.
     *
     *  <p><b>Note:</b> The Application container does not monitor the
     *  <code>controlBarGroup</code> property.
     *  If other code makes it invisible, the Application container might
     *  not update correctly.</p>
     *
     *  @default true
     *
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public function get controlBarVisible():Boolean
    {
        return (controlBarGroup)
            ? controlBarGroup.visible
            : controlBarGroupProperties.visible;
    }

    public function set controlBarVisible(value:Boolean):void
    {
        if (controlBarGroup)
        {
            controlBarGroup.visible = value;
            controlBarGroupProperties = BitFlagUtil.update(controlBarGroupProperties as uint,
                                                        VISIBLE_PROPERTY_FLAG, value);
        }
        else
            controlBarGroupProperties.visible = value;

        invalidateSkinState();
        if (skin)
            skin.invalidateSize();
    }

    //--------------------------------------------------------------------------
    //
    //  Compile-time pseudo-properties
    //
    //--------------------------------------------------------------------------

    // These declarations correspond to the MXML-compile-time attributes
    // allowed on the <Application> tag. These attributes affect the MXML
    // compiler, but they aren't actually used in the runtime framework.
    // The declarations appear here in order to provide metadata about these
    // attributes for Flash Builder.

    //----------------------------------
    //  frameRate
    //----------------------------------

    [Inspectable(defaultValue="24")]

    /**
     *    Specifies the frame rate of the application.
     *
     *    <p><b>Note:</b> This property cannot be set by ActionScript code; it must be set in MXML code.</p>
     *
     *    @default 24
     *
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public var frameRate:Number;

    //----------------------------------
    //  pageTitle
    //----------------------------------

    /**
     *    Specifies a string that appears in the title bar of the browser.
     *    This property provides the same functionality as the
     *    HTML <code>&lt;title&gt;</code> tag.
     *
     *    <p><b>Note:</b> This property cannot be set by ActionScript code; it must be set in MXML code.
     *    The value set in MXML code is designed to be used by a tool to update the HTML templates
     *    provided with the SDK.</p>
     *
     *    @default ""
     *
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public var pageTitle:String;

    //----------------------------------
    //  preloader
    //----------------------------------

    [Inspectable(defaultValue="mx.preloaders.DownloadProgressBar")]

    /**
     *  The application container supports an application preloader that 
     *  uses a download progress bar to show the download and initialization progress 
     *  of an application SWF file. 
     *  By default, the application preloader is enabled. 
     *  The preloader tracks how many bytes have been downloaded and continually 
     *  updates the progress bar. 
     *
     *  <p>Use this property to specify the path of a 
     *  component that defines a custom progress indicator.
     *  To create a custom progress indicator, you typically create a subclass of the 
     *  SparkDownloadProgressBar or DownloadProgressBar class, or create a subclass of 
     *  the flash.display.Sprite class that implements the 
     *  mx.preloaders.IPreloaderDisplay interface. </p>
     *
     *  <p><b>Note:</b> This property cannot be set by ActionScript code; it must be set in MXML code.</p>
     *
     *  @see mx.preloaders.SparkDownloadProgressBar 
     *  @see mx.preloaders.DownloadProgressBar 
     *  @see flash.display.Sprite
     *  @see mx.preloaders.IPreloaderDisplay
     *
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public var preloader:Object;

    //----------------------------------
    //  preloaderChromeColor
    //----------------------------------

    [Inspectable(defaultValue="0xCCCCCC", format="Color")]

    /**
     *  Specifies the chrome color used by the default preloader component. This property
     *  has the same effect as the <code>chromeColor</code> style used by Spark skins.
     *  Typically this property should be set to the same value as the
     *  Application container's <code>chromeColor</code> style property.
     *
     *  <p>Note: This property cannot be set by ActionScript code; it must be set in MXML code.</p>
     *
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */

    /* This property is not directly read by the download progress bar (preloader)
     * component. It is here so that it gets picked up by the compiler and included
     * in the info() structure for the generated system manager. The download progress bar
     * grabs the value directly from the info() structure. */
    public var preloaderChromeColor:uint;

    //----------------------------------
    //  scriptRecursionLimit
    //----------------------------------

    [Inspectable(defaultValue="1000")]

    /**
     *    Specifies the maximum depth of Flash Player or AIR
     *    call stack before the player stops.
     *    This is essentially the stack overflow limit.
     *
     *    <p><b>Note:</b> This property cannot be set by ActionScript code; it must be set in MXML code.</p>
     *
     *    @default 1000
     *
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public var scriptRecursionLimit:int;

    //----------------------------------
    //  scriptTimeLimit
    //----------------------------------

    [Inspectable(defaultValue="60")]

    /**
     *    Specifies the maximum duration, in seconds, that an ActionScript
     *    event handler can execute before Flash Player or AIR assumes
     *    that it is hung, and aborts it.
     *    The maximum allowable value that you can set is 60 seconds.
     *
     *  @default 60
     *
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public var scriptTimeLimit:Number;

    //----------------------------------
    //  splashScreenImage
    //----------------------------------

    /**
     *  The image class for the SplashScreen preloader.
     *  Typically you set this property to either an embedded resource
     *  or the name of a <code>SplashScreenImage</code> class defined in a separate MXML file.
     *  Example of setting splashScreenImage to an embedded image:
     *
     *  <pre>splashScreenImage="&#64;Embed('Default.png')"</pre>
     *
     *  <p><b>Note:</b> The property has effect only when the <code>preloader</code>
     *  property is set to spark.preloaders.SplashScreen.
     *  The spark.preloaders.SplashScreen class is the default preloader for Mobile Flex applications.
     *  This property cannot be set by ActionScript code; it must be set in MXML code.</p>
     *
     *  <p><b>Note:</b> You must add the frameworks\libs\mobile\mobilecomponents.swc to the 
     *  library path of the application to support the splash screen in a desktop application.</p>
     *
     *  @see spark.preloaders.SplashScreen
     *  @see #splashScreenScaleMode
     *  @see #splashScreenMinimumDisplayTime
     *
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get splashScreenImage():Class
    {
        // When set through mxml, the compiler uses the value in the generated loader class.
        return systemManager.info()["splashScreenImage"];
    }
    
    /**
     *  @private
     */
    public function set splashScreenImage(value:Class):void
    {
        systemManager.info()["splashScreenImage"] = value;
    }

    //----------------------------------
    //  splashScreenScaleMode
    //----------------------------------

    [Inspectable(enumeration="none,letterbox,stretch,zoom", defaultValue="none")]

    /**
     *  The splash screen image scale mode:
     *  
     *  <ul>
     *      <li>A value of <code>none</code> implies that the image size is set 
     *      to match its intrinsic size.</li>
     *
     *      <li>A value of <code>stretch</code> sets the width and the height of the image to the
     *      stage width and height, possibly changing the content aspect ratio.</li>
     *
     *      <li>A value of <code>letterbox</code> sets the width and height of the image 
     *      as close to the stage width and height as possible while maintaining aspect ratio.  
     *      The image is stretched to a maximum of the stage bounds,
     *      with spacing added inside the stage to maintain the aspect ratio if necessary.</li>
     *
     *      <li>A value of <code>zoom</code> is similar to <code>letterbox</code>, except 
     *      that <code>zoom</code> stretches the image past the bounds of the stage, 
     *      to remove the spacing required to maintain aspect ratio.
     *      This setting has the effect of using the entire bounds of the stage, but also 
     *      possibly cropping some of the image.</li>
     *  </ul>
     *
     *  <p>The portion of the stage that is not covered by the image shows 
     *  in the Application container's <code>backgroundColor</code>.</p>
     *
     *  <p><b>Note:</b> The property has effect only when the <code>splashScreenImage</code> property 
     *  is set and the <code>preloader</code> property is set to spark.preloaders.SplashScreen.
     *  The spark.preloaders.SplashScreen class is the default preloader for Mobile Flex applications.
     *  This property cannot be set by ActionScript code; it must be set in MXML code.</p>
     *
     *  <p><b>Note:</b> You must add the frameworks\libs\mobile\mobilecomponents.swc to the 
     *  library path of the application to support the splash screen in a desktop application.</p>
     *
     *  @default "none"
     *  @see #splashScreenImage
     *  @see #splashScreenMinimumDisplayTime
     *
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public var splashScreenScaleMode:String;

    //----------------------------------
    //  splashScreenMinimumDisplayTime
    //----------------------------------

    /**
     *  Minimum amount of time, in milliseconds, to show the splash screen image.
     *  Specify the splash screen image by using the <code>splashScreenImage</code> property.
     *
     *  <p><b>Note:</b> The property has effect only when the <code>splashScreenImage</code> property 
     *  is set and the <code>preloader</code> property is set to spark.preloaders.SplashScreen.
     *  The spark.preloaders.SplashScreen class is the default preloader for Mobile Flex applications.
     *  This property cannot be set by ActionScript code; it must be set in MXML code.</p>
     *
     *  <p><b>Note:</b> You must add the frameworks\libs\mobile\mobilecomponents.swc to the 
     *  library path of the application to support the splash screen in a desktop application.</p>
     *
     *  @default 1000
     * 
     *  @see #splashScreenImage
     *  @see #splashScreenScaleMode
     *
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public var splashScreenMinimumDisplayTime:Number;
    
    //----------------------------------
    //  applicationDPI
    //----------------------------------
    
    /**
     *  Storage for the applicationDPI property.
     * 
     *  @private
     */
    private var _applicationDPI:Number = NaN;
    
    [Inspectable(category="General", enumeration="120,160,240,320,480,640")]
    
    /**
     *  The DPI of the application.
     *  
     *  By default, this is the DPI of the device that the application is currently running on.
     * 
     *  When set in MXML, Flex will scale the Application to match its DPI to the
     *  <code>runtimeDPI</code>.
     *  
     *  This property cannot be set by ActionScript code; it must be set in MXML code.
     * 
     *  @see #runtimeDPI
     *  @see mx.core.DPIClassification
     *
     *  @langversion 3.0
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get applicationDPI():Number
    {
        if (isNaN(_applicationDPI))
        {
            var value:String = systemManager.info()["applicationDPI"];
            _applicationDPI = value ? Number(value) : runtimeDPI;
        }
        
        return _applicationDPI;
    }
    
    /**
     *  @private
     */
    public function set applicationDPI(value:Number):void
    {
        // Can't change at run-time so do nothing here.
        // The compiler will propagate the MXML value to the
        // systemManager's info object.
    }
    
    //----------------------------------
    //  runtimeDPI
    //----------------------------------
    
    /**
     *  The DPI of the device the application is currently running on.
     *
     *  Flex rounds the value to one of the <code>DPIClassification</code> choices. 
     *   
     *  @see #applicationDPI
     *  @see mx.core.DPIClassification
     *
     *  @langversion 3.0
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */  
    public function get runtimeDPI():Number
    {
        return DensityUtil.getRuntimeDPI();
    }
    
    //----------------------------------
    //  runtimeDPIProvider
    //----------------------------------
    
    /**
     *  A class that extends RuntimeDPIProvider and overrides the default Flex
     *  calculations for <code>runtimeDPI</code>.
     * 
     *  <p>Flex's default mappings are:
     *     <table class="innertable">
     *        <tr><td>160 DPI</td><td>&lt;140 DPI</td></tr>
     *        <tr><td>160 DPI</td><td>&gt;=140 DPI and &lt;=200 DPI</td></tr>
     *        <tr><td>240 DPI</td><td>&gt;=200 DPI and &lt;=280 DPI</td></tr>
     *        <tr><td>320 DPI</td><td>&gt;=280 DPI and &lt;=400 DPI</td></tr>
     *        <tr><td>480 DPI</td><td>&gt;=400 DPI and &lt;=560 DPI</td></tr>
     *        <tr><td>640 DPI</td><td>&gt;=640 DPI</td></tr>
     *     </table>
     *  </p>
     * 
     *  This property cannot be set by ActionScript code; it must be set in MXML code.
     * 
     *  @default spark.components.RuntimeDPIProvider
     * 
     *  @see #applicationDPI
     *  @see #runtimeDPI
     *  @see mx.core.DPIClassification
     *  @see mx.core.RuntimeDPIProvider
     *
     *  @langversion 3.0
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get runtimeDPIProvider():Class
    {
        return systemManager.info()["runtimeDPIProvider"];
    }
    
    /**
     *  @private
     */
    public function set runtimeDPIProvider(value:Class):void
    {
        // Can't change at run-time so do nothing here.
        // The compiler will propagate the MXML value to the
        // systemManager's info object.
    }
        
    //----------------------------------
    //  usePreloader
    //----------------------------------

    [Inspectable(defaultValue="true")]

    /**
     *    If <code>true</code>, specifies to display the application preloader.
     *
     *    <p><b>Note:</b> This property cannot be set by ActionScript code; it must be set in MXML code.</p>
     *
     *    @default true
     *
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public var usePreloader:Boolean;

    //--------------------------------------------------------------------------
    //
    //  Overridden properties (to block metadata from superclasses)
    //
    //--------------------------------------------------------------------------

    //----------------------------------
    //  id
    //----------------------------------

    [Inspectable(environment="none")]

    /**
     *  @private
     */
    override public function get id():String
    {
        if (!super.id &&
            this == FlexGlobals.topLevelApplication &&
            ExternalInterface.available)
        {
            return ExternalInterface.objectID;
        }

        return super.id;
    }

    //----------------------------------
    //  percentHeight
    //----------------------------------

    /**
     *  @private
     */
    override public function set percentHeight(value:Number):void
    {
        if (value != super.percentHeight)
        {
            super.percentHeight = value;
            percentBoundsChanged = true;
            invalidateProperties();
        }
    }

    //----------------------------------
    //  percentWidth
    //----------------------------------

    /**
     *  @private
     */
    override public function set percentWidth(value:Number):void
    {
        if (value != super.percentWidth)
        {
            super.percentWidth = value;
            percentBoundsChanged = true;
            invalidateProperties();
        }
    }

    //----------------------------------
    //  tabIndex
    //----------------------------------

    [Inspectable(environment="none")]

    /**
     *  @private
     */
    override public function set tabIndex(value:int):void
    {
    }

    //----------------------------------
    //  toolTip
    //----------------------------------

    [Inspectable(environment="none")]

    /**
     *  @private
     */
    override public function set toolTip(value:String):void
    {
    }

    //--------------------------------------------------------------------------
    //
    //  Properties
    //
    //--------------------------------------------------------------------------

    //----------------------------------
    //  aspectRatio
    //----------------------------------
    
    /**
     *  Returns the aspect ratio of the top level stage based on its width
     *  and height.  If the width of the stage is greater than the height,
     *  the stage is considered to be in "landscape" orientation.  Otherwise,
     *  portrait is returned.
     *  
	 *  @return This method will return "landscape" if the application is
	 *  in a landsacpe orientation, and "portrait" otherwise.
	 * 
     *  @langversion 3.0
     *  @playerversion Flash 10.2
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public function get aspectRatio():String
    {
		var actualHeight:Number = height;

		// If the application has resized itself in response to the
		// softKeyboard becoming visible, we need to compare against
		// the height without the keyboard active
		if (isSoftKeyboardActive && softKeyboardBehavior == "none" && resizeForSoftKeyboard)
			actualHeight += softKeyboardRect.height;
		
        return width > actualHeight ? "landscape" : "portrait";
    }
    
    //----------------------------------
    //  parameters
    //----------------------------------

    /**
     *  @private
     *  Storage for the parameters property.
     *  This variable is set in the initialize() method of SystemManager.
     */
    mx_internal var _parameters:Object;

    /**
     *  An Object containing name-value
     *  pairs representing the parameters provided to this Application.
     *
     *  <p>You can use a for-in loop to extract all the names and values
     *  from the parameters Object.</p>
     *
     *  <p>There are two sources of parameters: the query string of the
     *  Application's URL, and the value of the FlashVars HTML parameter
     *  (this affects only the main Application).</p>
     *
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public function get parameters():Object
    {
        return _parameters;
    }

    //----------------------------------
    //  resizeForSoftKeyboard
    //----------------------------------
    private var _resizeForSoftKeyboard:Boolean = false;
    
    /**
     *  Some devices do not support a hardware keyboard. 
     *  Instead, these devices use a keyboard that opens on 
     *  the screen when necessary. 
     *  The screen keyboard, also called a soft or virtual keyboard, 
     *  closes after the user enters the information, or when the user cancels the operation.
     *  A value of <code>true</code> means the application 
     *  is resized when the soft keyboard is open or
     *  closed.  
     *
     *  <p>To enable application resizing, you must also set the 
     *  <code>&lt;softKeyboardBehavior&gt;</code> attribute in the 
     *  application's xml descriptor file to <code>none</code>.</p>
     * 
     *  @default false
     *
     *  @langversion 3.0
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */ 
    public function get resizeForSoftKeyboard():Boolean
    {
        return _resizeForSoftKeyboard;
    }
    
    public function set resizeForSoftKeyboard(value:Boolean):void
    {
        if (_resizeForSoftKeyboard != value)
        {
            _resizeForSoftKeyboard = value;
        }
    }
    
    //----------------------------------
    //  url
    //----------------------------------

    /**
     *  @private
     *  Storage for the url property.
     *  This variable is set in the initialize().
     */
    mx_internal var _url:String;

    /**
     *  The URL from which this Application's SWF file was loaded.
     *
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public function get url():String
    {
        return _url;
    }

    //----------------------------------
    //  viewSourceURL
    //----------------------------------

    /**
     *  @private
     *  Storage for viewSourceURL property.
     */
    private var _viewSourceURL:String;

    /**
     *  URL where the application's source can be viewed. Setting this
     *  property inserts a "View Source" menu item into the application's
     *  default context menu.  Selecting the menu item opens the
     *  <code>viewSourceURL</code> in a new window.
     *
     *  <p>You must set the <code>viewSourceURL</code> property
     *  using MXML, not using ActionScript, as the following example shows:</p>
     *
     *  <pre>
     *    &lt;Application viewSourceURL="http://path/to/source"&gt;
     *      ...
     *    &lt;/Application&gt;</pre>
     *
     *
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public function get viewSourceURL():String
    {
        return _viewSourceURL;
    }

    /**
     *  @private
     */
    public function set viewSourceURL(value:String):void
    {
        _viewSourceURL = value;
    }

    //--------------------------------------------------------------------------
    //
    //  Overridden methods: UIComponent
    //
    //--------------------------------------------------------------------------

    /**
     *  @private
     */
    override protected function invalidateParentSizeAndDisplayList():void
    {
        if (!includeInLayout)
            return;

        var p:IInvalidating = parent as IInvalidating;
        if (!p)
        {
            if (parent is ISystemManager)
                ISystemManager(parent).invalidateParentSizeAndDisplayList();

            return;
        }

        super.invalidateParentSizeAndDisplayList();
    }

    /**
     *  @private
     */
    override public function initialize():void
    {
        // trace("FxApp initialize FxApp");

        var sm:ISystemManager = systemManager;

        // add listener if one is already attached
        if (hasEventListener(UncaughtErrorEvent.UNCAUGHT_ERROR))
            systemManager.loaderInfo.uncaughtErrorEvents.addEventListener(UncaughtErrorEvent.UNCAUGHT_ERROR, uncaughtErrorRedispatcher);

        // Determine if we are running on an iOS device
        isIOS = Platform.isIOS;
        
        // To prevent a flicker described in SDK-30133, a flex application listens
        // for orientationChanging events dispatched by iOS AIR applications.
        // In the handler, the stage's width and height are swapped, and a validation
        // pass is forced to allow the application to resize and re-layout itself before the
        // orientation change animation occurs
        if (isIOS && sm && sm.stage && sm.isTopLevelRoot())
        {
            sm.stage.addEventListener("orientationChanging", stage_orientationChangingHandler);
            sm.stage.addEventListener("orientationChange", stage_orientationChange);
            sm.stage.addEventListener(FullScreenEvent.FULL_SCREEN, stage_fullScreenHandler)  ;

            // if full screen app,  clear status bar height
            if ( sm.stage.displayState == StageDisplayState.FULL_SCREEN || sm.stage.displayState == StageDisplayState.FULL_SCREEN_INTERACTIVE )  {
                setStyle("osStatusBarHeight", 0);
            }
        }
        
        _url = LoaderUtil.normalizeURL(sm.loaderInfo);
        _parameters = sm.loaderInfo.parameters;

        initManagers(sm);

        // Setup the default context menu here. This allows the application
        // developer to override it in the initialize event, if desired.
        initContextMenu();

        super.initialize();

        // Stick a timer here so that we will execute script every 1.5s
        // no matter what.
        // This is strictly for the debugger to be able to halt.
        // Note: isDebugger is true only with a Debugger Player.
        if (sm.isTopLevel() && Capabilities.isDebugger == true)
            setInterval(debugTickler, 1500);
    }
    
    /**
     *  @private
     *  This is the event handler for the stage's orientationChanging event.  It
     *  cancels the orientation animation and manually swaps the width and height
     *  of the application to allow the application to validate itself before
     *  the orientation change occurs.  The orientaitonChanging is only listened
     *  for on iOS devices.
     */
    private function stage_orientationChangingHandler(event:Event):void
    {
        var sm:ISystemManager = systemManager;
        
        // Manually update orientation width and height if the application's explicit
        // sizes aren't set.  If they are, we assume the application will handle
        // orientation on their own.
        // SDK-30625: check stage for null since the Application may not be on-screen yet
        // if orientation changes during start-up.
        if (!stage || !isNaN(explicitWidth) || !isNaN(explicitHeight))
            return;

        if (!cachedDimensions)
            cachedDimensions = new Dictionary();
        
        // remember the current dimensions
        previousWidth = width;
        previousHeight = height;
        
        var key:String = width + ":" + height;
        
        // On some platforms (e.g. iOS and Playbook) if the soft keyboard is up
        // it deactivates before orientation change and reactivates after it; 
        // the value of isSoftKeyboardActive thus changes during orientation change.
        // We are remembering the initial value of isSoftKeyboardActivate in this
        // situation for use in avoiding excessive resizing during the orientation change.
        keyboardActiveInOrientationChange = isSoftKeyboardActive;

        // if we're rotating 180 degrees don't do any screen resizing
        var beforeOrientation:String = event["beforeOrientation"];
        var afterOrientation:String = event["afterOrientation"];
        
        if ((beforeOrientation == "default" && afterOrientation == "upsideDown") ||
            (beforeOrientation == "upsideDown" && afterOrientation == "default") ||
            (beforeOrientation == "rotatedLeft" && afterOrientation == "rotatedRight") ||
            (beforeOrientation == "rotatedRight" && afterOrientation == "rotatedLeft"))
            return;

        var newWidth:Number;
        var newHeight:Number;

        // if we have a cached value, use it
        if (cachedDimensions[key])
        {
            newWidth = cachedDimensions[key].width;
            newHeight = cachedDimensions[key].height;
        }
        else // no cached value; just swap the numbers for now
        {
            // use stageHeight as the new width if you can get it
            newWidth = stage ? stage.stageHeight / scaleFactor : height;
            newHeight = width;
        }
        
        setActualSize(newWidth, newHeight);
        
        // Indicate that the width and height have changed because of orientation 
        explicitSizingForOrientation = true;
        
        // Force a validation
        validateNow();
    }
    
    /**
     *  @private
     *  Handler for the stage orientation change event.  At this point, we need
     *  to undo the explicit width and height that was set when the application is
     *  reoriented on an iOS device.  See stage_orientationChangingHandler for more
     *  information.
     */
    private function stage_orientationChange(event:Event):void
    {
        // SDK-30625: check stage for null since the Application may not be on-screen yet
        // if orientation changes during start-up.
        if (!stage || !explicitSizingForOrientation)
            return;

        // update cache if keyboard was not previously active
        if (!keyboardActiveInOrientationChange)
        {
            updateScreenSizeCache(stage.stageWidth / scaleFactor, stage.stageHeight / scaleFactor);
        }
        
        explicitSizingForOrientation = false;
    }

    /** @private previous value of osStatusBarHeight on iOS when switch to full screen
     *
     */
    protected var savedOsStatusBarHeight: Number = 0;

    /**
     *  @private
     *  Handler to temporarily remove osStatusBarHeight is stage is set to full screen
     *  only of iOS devices
     */
    protected function stage_fullScreenHandler(event: FullScreenEvent): void {

        if (stage.displayState  == StageDisplayState.FULL_SCREEN ||  stage.displayState == StageDisplayState.FULL_SCREEN_INTERACTIVE) {
            var statusBarHeight : Number = getStyle("osStatusBarHeight");
            if (statusBarHeight > 0) {
                savedOsStatusBarHeight = statusBarHeight;
                setStyle("osStatusBarHeight", 0) ;
            }
        }
        else
        {
              if (savedOsStatusBarHeight > 0)    {
                  setStyle("osStatusBarHeight", savedOsStatusBarHeight);
                  savedOsStatusBarHeight = 0;
              }
        }
    }

    /**
     *  @private 
     *  Update the screen size cache with the new values. The previous values are
     *  pulled from the values currently set in the cache.
     *  Note that if the old and new width/height values are unchanged no values are
     *  cached under the assumption that this was a 180 degree rotation.
     * 
     */
    private function updateScreenSizeCache(newWidth:Number, newHeight:Number):void
    {
        // same dimensions, probably 180 degree rotation; don't cache
        if (previousWidth == newWidth && previousHeight == newHeight)
            return;
        
        var key:String = previousWidth + ":" + previousHeight;
        
        if (cachedDimensions[key])
        {
            // update the cached values if they are different
            cachedDimensions[key].width = newWidth;
            cachedDimensions[key].height = newHeight;
        }
        else
        {
            var orientationChangeKey:String = previousWidth + ":" + previousHeight;
            var reverseOrientationChangeKey:String = newWidth + ":" + newHeight;
            
            // cache values both ways, i.e. old -> new and new -> old
            cachedDimensions[orientationChangeKey] = {
                width:newWidth,
                height:newHeight
            };
            cachedDimensions[reverseOrientationChangeKey] = {
                width:previousWidth,
                height:previousHeight
            };
        }
    }
    
    
    /**
     *  @private
     */
    override protected function createChildren():void
    {
        super.createChildren();
        
        // Only listen for softKeyboard events 
        // if the runtime supports a soft keyboard
        if (softKeyboardBehavior != "")
        {
            addEventListener(SoftKeyboardEvent.SOFT_KEYBOARD_ACTIVATE, 
                softKeyboardActivateHandler, true, 
                EventPriority.DEFAULT, true);
            addEventListener(SoftKeyboardEvent.SOFT_KEYBOARD_DEACTIVATE, 
                softKeyboardDeactivateHandler, true, 
                EventPriority.DEFAULT, true);
            
            // Listen for the deactivate event so we can close the softKeyboard
            var nativeApp:Object = FlexGlobals.topLevelApplication.
                systemManager.getDefinitionByName("flash.desktop.NativeApplication");
            
            if (nativeApp && nativeApp["nativeApplication"])
                EventDispatcher(nativeApp["nativeApplication"]).
                    addEventListener(Event.DEACTIVATE, nativeApplication_deactivateHandler);
        }
    }

    /**
     *  @private
     */
    override protected function commitProperties():void
    {
        super.commitProperties();

        resizeWidth = isNaN(explicitWidth);
        resizeHeight = isNaN(explicitHeight);

        if (resizeWidth || resizeHeight)
        {
            resizeHandler(new Event(Event.RESIZE));

            if (!resizeHandlerAdded)
            {
                // weak reference
                systemManager.addEventListener(Event.RESIZE, resizeHandler, false, 0, true);
                resizeHandlerAdded = true;
            }
        }
        else
        {
            if (resizeHandlerAdded)
            {
                systemManager.removeEventListener(Event.RESIZE, resizeHandler);
                resizeHandlerAdded = false;
            }
        }

        if (percentBoundsChanged)
        {
            updateBounds();
            percentBoundsChanged = false;
        }
    }

    /**
     *  @private
     */
    override protected function resourcesChanged():void
    {
        super.resourcesChanged();

        // "View Source" on the context menu
        if (viewSourceCMI)
        {
            viewSourceCMI.caption = resourceManager.getString("components", "viewSource");
        }
    }

    /**
     *  @private
     */
    override protected function partAdded(partName:String, instance:Object):void
    {
        super.partAdded(partName, instance);

        if (instance == controlBarGroup)
        {
            // copy proxied values from controlBarGroupProperties (if set) to contentGroup
            var newControlBarGroupProperties:uint = 0;

            if (controlBarGroupProperties.controlBarContent !== undefined)
            {
                controlBarGroup.mxmlContent = controlBarGroupProperties.controlBarContent;
                newControlBarGroupProperties = BitFlagUtil.update(newControlBarGroupProperties,
                                                               CONTROLBAR_PROPERTY_FLAG, true);
            }

            if (controlBarGroupProperties.layout !== undefined)
            {
                controlBarGroup.layout = controlBarGroupProperties.layout;
                newControlBarGroupProperties = BitFlagUtil.update(newControlBarGroupProperties,
                                                               LAYOUT_PROPERTY_FLAG, true);
            }

            if (controlBarGroupProperties.visible !== undefined)
            {
                controlBarGroup.visible = controlBarGroupProperties.visible;
                newControlBarGroupProperties = BitFlagUtil.update(newControlBarGroupProperties,
                                                               VISIBLE_PROPERTY_FLAG, true);
            }

            controlBarGroupProperties = newControlBarGroupProperties;
        }
    }

    /**
     *  @private
     *
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    override protected function partRemoved(partName:String, instance:Object):void
    {
        super.partRemoved(partName, instance);

        if (instance == controlBarGroup)
        {
            // copy proxied values from contentGroup (if explicitely set) to contentGroupProperties

            var newControlBarGroupProperties:Object = {};

            if (BitFlagUtil.isSet(controlBarGroupProperties as uint, CONTROLBAR_PROPERTY_FLAG))
                newControlBarGroupProperties.controlBarContent = controlBarGroup.getMXMLContent();

            if (BitFlagUtil.isSet(controlBarGroupProperties as uint, LAYOUT_PROPERTY_FLAG))
                newControlBarGroupProperties.layout = controlBarGroup.layout;

            if (BitFlagUtil.isSet(controlBarGroupProperties as uint, VISIBLE_PROPERTY_FLAG))
                newControlBarGroupProperties.visible = controlBarGroup.visible;

            controlBarGroupProperties = newControlBarGroupProperties;

            controlBarGroup.mxmlContent = null;
            controlBarGroup.layout = null;
        }
    }

    /**
     *  @private
     *
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    override protected function getCurrentSkinState():String
    {
        var state:String = enabled ? "normal" : "disabled";
        if (controlBarGroup)
        {
            if (BitFlagUtil.isSet(controlBarGroupProperties as uint, CONTROLBAR_PROPERTY_FLAG) &&
                BitFlagUtil.isSet(controlBarGroupProperties as uint, VISIBLE_PROPERTY_FLAG))
                state += "WithControlBar";
        }
        else
        {
            if (controlBarGroupProperties.controlBarContent &&
                controlBarGroupProperties.visible)
                state += "WithControlBar";
        }

        return state;
    }
    
    
    /**
     *  @private 
     */
    override public function styleChanged(styleProp:String):void
    {
        super.styleChanged(styleProp);
        
        if (!styleProp || styleProp == "styleName" || styleProp == "interactionMode")
        {
            // Turn off tooltip support for all mobile applications
            ToolTipManager.enabled = getStyle("interactionMode") != InteractionMode.TOUCH;
        }
    }

    //----------------------------------
    //  unscaledHeight
    //----------------------------------

    /**
     *  @private
     */
    override mx_internal function setUnscaledHeight(value:Number):void
    {
        // we invalidate so we can properly add/remove the resize
        // event handler (SDK-12664)
        invalidateProperties();

        super.setUnscaledHeight(value);
    }

    //----------------------------------
    //  unscaledWidth
    //----------------------------------

    /**
     *  @private
     */
    override mx_internal function setUnscaledWidth(value:Number):void
    {
        // we invalidate so we can properly add/remove the resize
        // event handler (SDK-12664)
        invalidateProperties();

        super.setUnscaledWidth(value);
    }

    //--------------------------------------------------------------------------
    //
    //  Methods
    //
    //--------------------------------------------------------------------------

    /**
     *  @private
     *  This is here so we get the this pointer set to Application.
     */
    private function debugTickler():void
    {
        // We need some bytes of code in order to have a place to break.
        var i:int = 0;
    }

    /**
     *  @private
     */
    private function initManagers(sm:ISystemManager):void
    {
        if (sm.isTopLevel())
        {
            focusManager = new FocusManager(this);
            var awm:IActiveWindowManager =
                IActiveWindowManager(sm.getImplementation("mx.managers::IActiveWindowManager"));
            if (awm)
                awm.activate(this);
            else
                focusManager.activate();
        }
    }

    /**
     *  @private
     *  Disable all the built-in items except "Print...".
     */
    private function initContextMenu():void
    {
        // context menu already set
        // nothing to init
        if (flexContextMenu != null)
        {
            // make sure we set it back on systemManager b/c it may have been overridden by now
            if (systemManager is InteractiveObject)
                InteractiveObject(systemManager).contextMenu = contextMenu as ContextMenu;
            return;
        }

        var defaultMenu:ContextMenu = new ContextMenu();
        defaultMenu.hideBuiltInItems();
        defaultMenu.builtInItems.print = true;

        if (_viewSourceURL)
        {
            // don't worry! this gets updated in resourcesChanged()
            const caption:String = resourceManager.getString("components", "viewSource");

            viewSourceCMI = new ContextMenuItem(caption, true);
            viewSourceCMI.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, menuItemSelectHandler);

            // Append custom option, validating customItems first as in the 
            // mobile context this is null.
            if (defaultMenu.customItems)
                defaultMenu.customItems.push(viewSourceCMI);
        }

        contextMenu = defaultMenu;

        if (systemManager is InteractiveObject)
            InteractiveObject(systemManager).contextMenu = defaultMenu;
    }

    /**
     *  @private
     *  Check to see if we're able to synchronize our size with the stage
     *  immediately rather than deferring (dependent on WATSON 2200950).
     */
    private function initResizeBehavior():void
    {
		var version:Array = Capabilities.version.split(' ')[1].split(',');
		
		synchronousResize = (parseFloat(version[0]) > 10 ||
			(parseFloat(version[0]) == 10 && parseFloat(version[1]) >= 1)) && !Platform.isAir;
    }
    
    /**
     *  @private
     *  Called if resizeForSoftKeyboard is true and the softKeyboard
     *  has been activated. 
     */    
    private function softKeyboardActivateHandler(event:SoftKeyboardEvent):void
    {        
        // Add a listener for the softKeyboard deactivate event to the event target
        event.target.addEventListener(SoftKeyboardEvent.SOFT_KEYBOARD_DEACTIVATE, 
                                      softKeyboardDeactivateHandler);
        
        if (this === FlexGlobals.topLevelApplication)
        {
            if (softKeyboardTarget && softKeyboardTarget != event.target)
                clearSoftKeyboardTarget();
            
            softKeyboardTarget = event.target;
            
            // If the display object that activates the softkeyboard is removed without
            // losing focus, the runtime may not dispatch a deactivate event.  So the
            // framework adds a REMOVE_FROM_STAGE event listener to the target and manually
            // clears the focus.
            softKeyboardTarget.addEventListener(Event.REMOVED_FROM_STAGE, 
                                                softKeyboardTarget_removeFromStageHandler, 
                                                false, EventPriority.DEFAULT, true);
            
            // On iOS, if the softKeyboard target is removed from the stage as a result
            // of a user input with another focusable component, the application will not
            // receive a SOFT_KEYBOARD_DEACTIVATE event, only the target will.
            if (isIOS)
            {
                softKeyboardTarget.addEventListener(SoftKeyboardEvent.SOFT_KEYBOARD_DEACTIVATE, 
                                                    softKeyboardDeactivateHandler, false, 
                                                    EventPriority.DEFAULT, true);
            }
            
            // Get the keyboard size
            var keyboardRect:Rectangle = softKeyboardRect;
     
            if (keyboardRect.height > 0)
                isSoftKeyboardActive = true;
            
            if (softKeyboardBehavior == "none" && resizeForSoftKeyboard)
            {
                var appHeight:Number = (stage.stageHeight - keyboardRect.height) / scaleFactor;
                var appWidth:Number = stage.stageWidth / scaleFactor;
                
                if (appHeight != height || appWidth != width)
                {
                    setActualSize(appWidth, appHeight);
                    validateNow(); // Validate so that other listeners like Scroller get the updated dimensions
                }
                
                // update the screen size cache
                if (keyboardActiveInOrientationChange)
                {
                    keyboardActiveInOrientationChange = false;
                    updateScreenSizeCache(appWidth, appHeight);
                }
            }
        }
    }
    
    /**
     *  @private
     *  Called if resizeForSoftKeyboard is true and the softKeyboard
     *  has been deactivated. 
     */ 
    private function softKeyboardDeactivateHandler(event:SoftKeyboardEvent):void
    {
        if (this === FlexGlobals.topLevelApplication && isSoftKeyboardActive)
        {            
            if (softKeyboardTarget)
                clearSoftKeyboardTarget();
            
            isSoftKeyboardActive = false;
            
            if (softKeyboardBehavior == "none" && resizeForSoftKeyboard && !keyboardActiveInOrientationChange)
            {
                // Restore the original values
                setActualSize(stage.stageWidth / scaleFactor, stage.stageHeight / scaleFactor);
                
                validateNow(); // Validate so that other listeners like Scroller get the updated dimensions
            }
        }
    }
    
    /**
     *  @private
     */
    private function nativeApplication_deactivateHandler(event:Event):void
    {
        // Close the softKeyboard if we deactivate the application. This works
        // around an iOS bug where the SoftKeyboard.DEACTIVATE event isn't
        // dispatched when the application is deactivated. 
        if (isSoftKeyboardActive)
        {
            stage.focus = null;
            softKeyboardDeactivateHandler(null);
        }
    }
    
    /**
     *  @private
     *  Called when a softKeyboard activation target is removed from the
     *  stage.  If the target has stage focus, then the focus is set to null.
     *  This will cause a SOFT_KEYBOARD_DEACTIVATE event to be dispatched.
     */ 
    private function softKeyboardTarget_removeFromStageHandler(event:Event):void
    {
        if (stage.focus == softKeyboardTarget)
            stage.focus = null;
        
        // clearSoftKeyboardTarget() is called in response to the SOFT_KEYBOARD_DEACTIVATE
        // event and will clear the removeFromStage listener and softKeyboardDeactivate 
        // events from the target.
    }
    
    /**
     *  @private
     *  This method clears the cached softKeyboard target and removes the
     *  removeFromStage handler that is added in the softKeyboardActivateHandler
     *  method.
     */
    private function clearSoftKeyboardTarget():void
    {
        if (softKeyboardTarget)
        {
            if (isIOS)
            {
                softKeyboardTarget.removeEventListener(SoftKeyboardEvent.SOFT_KEYBOARD_DEACTIVATE, 
                                                       softKeyboardDeactivateHandler);
            }
            
            softKeyboardTarget.removeEventListener(Event.REMOVED_FROM_STAGE, softKeyboardTarget_removeFromStageHandler);
            softKeyboardTarget = null;
        }
    }
    
    /**
     *  Helper function to get the AIR application descriptor attribute called "softKeyboardBehavior". 
     */  
    mx_internal static function get softKeyboardBehavior():String
    {
        if (_softKeyboardBehavior != null)
        {
            return _softKeyboardBehavior;
        }
        else
        {
            // Since we might not be running on AIR, need to get the class by name. 
            // Also, make sure to cache the value so we only run this once
            var nativeApp:Object = FlexGlobals.topLevelApplication.systemManager.getDefinitionByName("flash.desktop.NativeApplication");
            
            if (nativeApp)
            {
                try
                {
                    var appXML:XML = XML(nativeApp["nativeApplication"]["applicationDescriptor"]);
                    var ns:Namespace = appXML.namespace();
                    
                    _softKeyboardBehavior = String(appXML..ns::softKeyboardBehavior);
                }
                catch (e:Error)
                {
                    // TODO (aharui): Marshall this someday?
                    _softKeyboardBehavior = "";
                }
            }
            else
            {
                _softKeyboardBehavior = "";
            }
            
            return _softKeyboardBehavior;
        }
    }

    //--------------------------------------------------------------------------
    //
    //  Event handlers
    //
    //--------------------------------------------------------------------------

    /**
     *  @private
     *  Triggered by a resize event of the stage.
     *  Sets the new width and height.
     *  After the SystemManager performs its function,
     *  it is only necessary to notify the children of the change.
     */
    private function resizeHandler(event:Event):void
    {
        // don't run while keyboard is up and orientation is changing
        if (keyboardActiveInOrientationChange)
            return;
        
        // If we're already due to update our bounds on the next
        // commitProperties pass, avoid the redundancy.
        if (!percentBoundsChanged)
        {
            updateBounds();

            // Update immediately when stage resizes so that we may appear
            // in synch with the stage rather than visually "catching up".
            if (synchronousResize)
                UIComponentGlobals.layoutManager.validateNow();
        }
    }

    /**
     *  @private
     *  Called when the "View Source" item in the application's context menu is
     *  selected.
     */
    protected function menuItemSelectHandler(event:Event):void
    {
        navigateToURL(new URLRequest(_viewSourceURL), "_blank");
    }

    /**
     *  @private
     *  Sets the new width and height after the Stage has resized
     *  or when percentHeight or percentWidth has changed.
     */
    private function updateBounds():void
    {
        // When user has not specified any width/height,
        // application assumes the size of the stage.
        // If developer has specified width/height,
        // the application will not resize.
        // If developer has specified percent width/height,
        // application will resize to the required value
        // based on the current SystemManager's width/height.
        // If developer has specified min/max values,
        // then application will not resize beyond those values.
        
        // ignore updateBounds while orientation is changing
        if (keyboardActiveInOrientationChange)
            return;
        
        var w:Number;
        var h:Number

        if (resizeWidth)
        {
            if (isNaN(percentWidth))
            {
                w = DisplayObject(systemManager).width;
            }
            else
            {
                super.percentWidth = Math.max(percentWidth, 0);
                super.percentWidth = Math.min(percentWidth, 100);
                w = percentWidth*DisplayObject(systemManager).width/100;
            }

            if (!isNaN(explicitMaxWidth))
                w = Math.min(w, explicitMaxWidth);

            if (!isNaN(explicitMinWidth))
                w = Math.max(w, explicitMinWidth);
        }
        else
        {
            w = width;
        }

        if (resizeHeight)
        {
            if (isNaN(percentHeight))
            {
                h = DisplayObject(systemManager).height;
            }
            else
            {
                super.percentHeight = Math.max(percentHeight, 0);
                super.percentHeight = Math.min(percentHeight, 100);
                h = percentHeight*DisplayObject(systemManager).height/100;
            }

            if (!isNaN(explicitMaxHeight))
                h = Math.min(h, explicitMaxHeight);

            if (!isNaN(explicitMinHeight))
                h = Math.max(h, explicitMinHeight);
        }
        else
        {
            h = height;
        }

        if (w != width || h != height)
        {
            invalidateProperties();
            invalidateSize();
        }

        setActualSize(w, h);

        invalidateDisplayList();
    }

    /**
     * @private
     */
    override public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void
    {
        // this can get called before we know our systemManager.  Hook it up later in initialize()
        if (type == UncaughtErrorEvent.UNCAUGHT_ERROR && systemManager)
            systemManager.loaderInfo.uncaughtErrorEvents.addEventListener(UncaughtErrorEvent.UNCAUGHT_ERROR, uncaughtErrorRedispatcher);
        super.addEventListener(type, listener, useCapture, priority, useWeakReference)
    }

    /**
     * @private
     */
    override public function removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void
    {
        super.removeEventListener(type, listener, useCapture);
        if (type == UncaughtErrorEvent.UNCAUGHT_ERROR && systemManager)
            systemManager.loaderInfo.uncaughtErrorEvents.removeEventListener(UncaughtErrorEvent.UNCAUGHT_ERROR, uncaughtErrorRedispatcher);
    }

    private function uncaughtErrorRedispatcher(event:Event):void
    {
        if (!dispatchEvent(event))
            event.preventDefault();
    }
	
	mx_internal var _softKeyboardRect:Rectangle;
	
	mx_internal function get softKeyboardRect():Rectangle
	{
		if (_softKeyboardRect == null)
			return stage.softKeyboardRect;
		
		return _softKeyboardRect;
	}
}

}
