////////////////////////////////////////////////////////////////////////////////
//
//  ADOBE SYSTEMS INCORPORATED
//  Copyright 2006-2007 Adobe Systems Incorporated
//  All Rights Reserved.
//
//  NOTICE: Adobe permits you to use, modify, and distribute this file
//  in accordance with the terms of the license agreement accompanying it.
//
////////////////////////////////////////////////////////////////////////////////

package mx.core
{

import flash.desktop.DockIcon;
import flash.desktop.NativeApplication;
import flash.desktop.SystemTrayIcon;
import flash.display.DisplayObject;
import flash.display.Graphics;
import flash.display.NativeWindow;
import flash.display.NativeWindowDisplayState;
import flash.display.NativeWindowResize;
import flash.display.NativeWindowSystemChrome;
import flash.display.NativeWindowType;
import flash.display.Screen;
import flash.display.Sprite;
import flash.display.StageDisplayState;
import flash.events.Event;
import flash.events.FullScreenEvent;
import flash.events.InvokeEvent;
import flash.events.MouseEvent;
import flash.events.NativeWindowBoundsEvent;
import flash.events.NativeWindowDisplayStateEvent;
import flash.filesystem.File;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.system.Capabilities;

import mx.controls.Alert;
import mx.controls.Button;
import mx.controls.FlexNativeMenu;
import mx.controls.HTML;
import mx.core.windowClasses.StatusBar;
import mx.core.windowClasses.TitleBar;
import mx.events.AIREvent;
import mx.events.EffectEvent;
import mx.events.FlexEvent;
import mx.events.FlexNativeWindowBoundsEvent;
import mx.managers.DragManager;
import mx.managers.NativeDragManagerImpl;
import mx.managers.SystemManagerGlobals;
import mx.styles.CSSStyleDeclaration;
import mx.styles.StyleManager;
import mx.styles.StyleProxy;

use namespace mx_internal;

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

/**
 *  Dispatched when this application is activated.
 *
 *  @eventType mx.events.AIREvent.APPLICATION_ACTIVATE
 *  
 *  @langversion 3.0
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Event(name="applicationActivate", type="mx.events.AIREvent")]

/**
 *  Dispatched when this application is deactivated.
 *
 *  @eventType mx.events.AIREvent.APPLICATION_DEACTIVATE
 *  
 *  @langversion 3.0
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Event(name="applicationDeactivate", type="mx.events.AIREvent")]

/**
 *  Dispatched after this application window has been activated.
 *
 *  @eventType mx.events.AIREvent.WINDOW_ACTIVATE
 *  
 *  @langversion 3.0
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Event(name="windowActivate", type="mx.events.AIREvent")]

/**
 *  Dispatched after this application window has been deactivated.
 *
 *  @eventType mx.events.AIREvent.WINDOW_DEACTIVATE
 *  
 *  @langversion 3.0
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Event(name="windowDeactivate", type="mx.events.AIREvent")]
 
/**
 *  Dispatched after this application window has been closed.
 *
 *  @eventType flash.events.Event.CLOSE
 *
 *  @see flash.display.NativeWindow
 *  
 *  @langversion 3.0
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Event(name="close", type="flash.events.Event")]

/**
 *  Dispatched before the WindowedApplication window closes.
 *  Cancelable.
 *
 *  @eventType flash.events.Event.CLOSING
 *
 *  @see flash.display.NativeWindow
 *  
 *  @langversion 3.0
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Event(name="closing", type="flash.events.Event")]

/**
 *  Dispatched after the display state changes to minimize, maximize
 *  or restore.
 *
 *  @eventType flash.events.NativeWindowDisplayStateEvent.DISPLAY_STATE_CHANGE
 *  
 *  @langversion 3.0
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Event(name="displayStateChange", type="flash.events.NativeWindowDisplayStateEvent")]

/**
 *  Dispatched before the display state changes to minimize, maximize
 *  or restore.
 *
 *  @eventType flash.events.NativeWindowDisplayStateEvent.DISPLAY_STATE_CHANGING
 *  
 *  @langversion 3.0
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Event(name="displayStateChanging", type="flash.events.NativeWindowDisplayStateEvent")]

/**
 *  Dispatched when an application is invoked.
 *  
 *  @langversion 3.0
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Event(name="invoke", type="flash.events.InvokeEvent")]

/**
 *  Dispatched before the WindowedApplication object moves,
 *  or while the WindowedApplication object is being dragged.
 *
 *  @eventType flash.events.NativeWindowBoundsEvent.MOVING
 *  
 *  @langversion 3.0
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Event(name="moving", type="flash.events.NativeWindowBoundsEvent")]

/**
 *  Dispatched when the computer connects to or disconnects from the network.
 *
 *  @eventType flash.events.Event.NETWORK_CHANGE
 *  
 *  @langversion 3.0
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Event(name="networkChange", type="flash.events.Event")]

/**
 *  Dispatched before the WindowedApplication object is resized,
 *  or while the WindowedApplication object boundaries are being dragged.
 *
 *  @eventType flash.events.NativeWindowBoundsEvent.RESIZING
 *  
 *  @langversion 3.0
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Event(name="resizing", type="flash.events.NativeWindowBoundsEvent")]

/**
 *  Dispatched when the WindowedApplication completes its initial layout.
 *  By default, the WindowedApplication will be visbile at this time.
 *
 *  @eventType mx.events.AIREvent.WINDOW_COMPLETE
 *  
 *  @langversion 3.0
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Event(name="windowComplete", type="mx.events.AIREvent")]

/**
 *  Dispatched after the WindowedApplication object moves.
 *
 *  @eventType mx.events.FlexNativeWindowBoundsEvent.WINDOW_MOVE
 *  
 *  @langversion 3.0
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Event(name="windowMove", type="mx.events.FlexNativeWindowBoundsEvent")]

/**
 *  Dispatched after the underlying NativeWindow object is resized.
 *
 *  @eventType mx.events.FlexNativeWindowBoundsEvent.WINDOW_RESIZE
 *  
 *  @langversion 3.0
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Event(name="windowResize", type="mx.events.FlexNativeWindowBoundsEvent")]

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

/**
 *  Position of buttons in title bar. Possible values: <code>"left"</code>,
 *  <code>"right"</code>, <code>"auto"</code>.
 *
 *  <p>A value of <code>"left"</code> means the buttons are aligned
 *  at the left of the title bar.
 *  A value of <code>"right"</code> means the buttons are aligned
 *  at the right of the title bar.
 *  A value of <code>"auto"</code> means the buttons are aligned
 *  at the left of the title bar on Mac OS X and on the
 *  right on Windows.</p>
 *
 *  @default "auto"
 *  
 *  @langversion 3.0
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="buttonAlignment", type="String", enumeration="left,right,auto", inherit="yes")]

/**
 *  Defines the distance between the titleBar buttons.
 *
 *  @default 2
 *  
 *  @langversion 3.0
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="buttonPadding", type="Number", inherit="yes")]

/**
 *  Skin for close button when using Flex chrome.
 *
 *  @default mx.skins.halo.WindowCloseButtonSkin
 *  
 *  @langversion 3.0
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="closeButtonSkin", type="Class", inherit="no",states="up, over, down, disabled")]

/**
 *  The extra space around the gripper. The total area of the gripper
 *  plus the padding around the edges is the hit area for the gripper resizing.
 *
 *  @default 3
 *  
 *  @langversion 3.0
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="gripperPadding", type="Number", format="Length", inherit="no")]

/**
 *  Style declaration for the skin of the gripper.
 *
 *  @default "gripperStyle"
 *  
 *  @langversion 3.0
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="gripperStyleName", type="String", inherit="no")]

/**
 *  The explicit height of the header. If this style is not set, the header
 *  height is calculated from the largest of the text height, the button
 *  heights, and the icon height.
 *
 *  @default undefined
 *  
 *  @langversion 3.0
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="headerHeight", type="Number", format="Length", inherit="no")]

/**
 *  Skin for maximize button when using Flex chrome.
 *
 *  @default mx.skins.halo.WindowMaximizeButtonSkin
 *  
 *  @langversion 3.0
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="maximizeButtonSkin", type="Class", inherit="no",states="up, over, down, disabled")]

/**
 *  Skin for minimize button when using Flex chrome.
 *
 *  @default mx.skins.halo.WindowMinimizeButtonSkin
 *  
 *  @langversion 3.0
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="minimizeButtonSkin", type="Class", inherit="no",states="up, over, down, disabled")]

/**
 *  Skin for restore button when using Flex chrome.
 *  This style is ignored for Mac OS X.
 *
 *  @default mx.skins.halo.WindowRestoreButtonSkin
 *  
 *  @langversion 3.0
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="restoreButtonSkin", type="Class", inherit="no",states="up, over, down, disabled")]

/**
 *  Determines whether the window draws its own Flex Chrome or depends on the developer
 *  to draw chrome. Changing this style once the window is open has no effect.
 *
 *  @default true
 *  
 *  @langversion 3.0
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="showFlexChrome", type="Boolean", inherit="no")]

/**
 *  The status bar background skin.
 *
 *  @default mx.skins.halo.StatusBarBackgroundSkin
 *  
 *  @langversion 3.0
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="statusBarBackgroundSkin", type="Class", inherit="yes")]

/**
 *  The colors used to draw the status bar.
 *
 *  @default 0xC0C0C0
 *  
 *  @langversion 3.0
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="statusBarBackgroundColor", type="uint", format="Color", inherit="yes")]

/**
 *  Style declaration for the status text.
 *
 *  @default undefined
 *  
 *  @langversion 3.0
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="statusTextStyleName", type="String", inherit="yes")]

/**
 *  Position of the title in title bar.
 *  The possible values are <code>"left"</code>,
 *  <code>"center"</code>, <code>"auto"</code>
 *
 *  <p>A value of <code>"left"</code> means the title is aligned
 *  at the left of the title bar.
 *  A value of <code>"center"</code> means the title is aligned
 *  at the center of the title bar.
 *  A value of <code>"auto"</code> means the title is aligned
 *  at the left on Windows and at the center on Mac OS X.</p>
 *
 *  @default "auto"
 *  
 *  @langversion 3.0
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="titleAlignment", type="String", enumeration="left,center,auto", inherit="yes")]

/**
 *  The title background skin.
 *
 *  @default mx.skins.halo.ApplicationTitleBarBackgroundSkin
 *  
 *  @langversion 3.0
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="titleBarBackgroundSkin", type="Class", inherit="yes")]

/**
 *  The distance between the furthest out title bar button and the
 *  edge of the title bar.
 *
 *  @default 5
 *  
 *  @langversion 3.0
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="titleBarButtonPadding", type="Number", inherit="true")]

/**
 *  An array of two colors used to draw the header.
 *  The first color is the top color.
 *  The second color is the bottom color.
 *  The default values are <code>undefined</code>, which
 *  makes the header background the same as the
 *  panel background.
 *
 *  @default [ 0x000000, 0x000000 ]
 *  
 *  @langversion 3.0
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="titleBarColors", type="Array", arrayType="uint", format="Color", inherit="yes")]

/**
 *  The style name for the title text.
 *
 *  @default undefined
 *  
 *  @langversion 3.0
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Style(name="titleTextStyleName", type="String", inherit="yes")]

//--------------------------------------
//  Effects
//--------------------------------------

/**
 *  Played when the window is closed.
 *  
 *  @langversion 3.0
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Effect(name="closeEffect", event="windowClose")]

/**
 *  Played when the component is minimized.
 *  
 *  @langversion 3.0
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Effect(name="minimizeEffect", event="windowMinimize")]

/**
 *  Played when the component is unminimized.
 *  
 *  @langversion 3.0
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
[Effect(name="unminimizeEffect", event="windowUnminimize")]

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

[Exclude(name="moveEffect", kind="effect")]
[Exclude(name="scriptTimeLimit", kind="property")]

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

[ResourceBundle("core")]

[Alternative(replacement="spark.components.WindowedApplication", since="4.0")]

/**
 *  The WindowedApplication defines the application container
 *  that you use to create Flex applications for AIR applications.
 *
 *  <p>The WindowedApplication serves two roles. It is a replacement for the &lt;mx:Application&gt;
 *  tag, functioning as the entry point to a Flex-based AIR application. In addition,
 *  as a container the WindowedApplication defines the layout of the initial window
 *  of a Flex AIR application -- any visual controls defined in the WindowedApplication
 *  become the content of the initial window loaded by the AIR application.</p>
 *
 *  <p>A WindowedApplication is the top-level application of a Flex-based AIR application. It is not
 *  designed to be loaded by other Flex applications. If a WindowedApplication needs to load other
 *  applications, use the Application class as container for those applications. If other windows
 *  are required, use the Window class as a container for those windows.</p>
 *  
 *  <p>Note that because
 *  the WindowedApplication only represents the visual content of a single window, and not
 *  all the windows in a multi-window application, a WindowedApplication instance only dispatches
 *  display-related events (events that the WindowedApplication class inherits from display object base
 *  classes such as InteractiveObject or UIComponent) for its own stage and window, and not for
 *  events that occur on other windows in the application. This differs from a browser-based application,
 *  where an Application container dispatches events for all the windows in the application (because
 *  technically those windows are all display objects rendered on the single Application stage).</p>
 *
 *  @mxml
 *
 *  <p>The <code>&lt;mx:WindowedApplication&gt;</code> tag inherits all of the tag
 *  attributes of its superclass and adds the following tag attributes:</p>
 *
 *  <pre>
 *  &lt;mx:WindowedApplication
 *    <strong>Properties</strong>
 *    alwaysInFront="false"
 *    autoExit="true"
 *    backgroundFrameRate="-1"
 *    dockIconMenu="<i>null</i>"
 *    maxHeight="2880 less the height of the system chrome"
 *    maxWidth="2880 less the width of the system chrome"
 *    menu="<i>null</i>"
 *    minHeight="dependent on the operating system and the AIR systemChrome setting"
 *    minWidth="dependent on the operating system and the AIR systemChrome setting"
 *    showGripper="true"
 *    showStatusBar="true"
 *    showTitleBar="true"
 *    status=""
 *    statusBarFactory="mx.core.ClassFactory"
 *    systemTrayIconMenu="<i>null</i>"
 *    title=""
 *    titleBarFactory="mx.core.ClassFactory"
 *    titleIcon="<i>null</i>"
 *    useNativeDragManager="true"
 * 
 *    <strong>Styles</strong>
 *    buttonAlignment="auto"
 *    buttonPadding="2"
 *    closeButtonSkin="mx.skins.halo.windowCloseButtonSkin"
 *    gripperPadding="3"
 *    gripperStyleName="gripperStyle"
 *    headerHeight="<i>undefined</i>"
 *    maximizeButtonSkin="mx.skins.halo.WindowMaximizeButtonSkin"
 *    minimizeButtonSkin="mx.skins.halo.WindowMinimizeButtonSkin"
 *    restoreButtonSkin="mx.skins.halo.WindowRestoreButtonSkin"
 *    showFlexChrome="true"
 *    statusBarBackgroundColor="0xC0C0C0"
 *    statusBarBackgroundSkin="mx.skins.halo.StatusBarBackgroundSkin"
 *    statusTextStyleName="<i>undefined</i>"
 *    titleAlignment="auto"
 *    titleBarBackgroundSkin="mx.skins.halo.ApplicationTitleBarBackgroundSkin"
 *    titleBarButtonPadding="5"
 *    titleBarColors="[ 0x000000, 0x000000 ]"
 *    titleTextStyleName="<i>undefined</i>"
 * 
 *    <strong>Effects</strong>
 *    closeEffect="<i>No default</i>"
 *    minimizeEffect="<i>No default</i>"
 *    unminimizeEffect="<i>No default</i>"
 * 
 *    <strong>Events</strong>
 *    applicationActivate="<i>No default</i>"
 *    applicationDeactivate="<i>No default</i>"
 *    closing="<i>No default</i>"
 *    displayStateChange="<i>No default</i>"
 *    displayStateChanging="<i>No default</i>"
 *    invoke="<i>No default</i>"
 *    moving="<i>No default</i>"
 *    networkChange="<i>No default</i>"
 *    resizing="<i>No default</i>"
 *    windowComplete="<i>No default</i>"
 *    windowMove="<i>No default</i>"
 *    windowResize="<i>No default</i>"
 *  /&gt;
 *  </pre>
 * 
 *  
 *  @langversion 3.0
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
public class WindowedApplication extends Application implements IWindow
{
    include "../core/Version.as";

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

    /**
     *  @private
     */
    private static const HEADER_PADDING:Number = 4;

    /**
     *  @private
     */
    private static const MOUSE_SLACK:Number = 5;

    //--------------------------------------------------------------------------
    //
    //  Class variables
    //
    //--------------------------------------------------------------------------

    /**
     *  @private
     *  This is here to force linkage of NativeDragManagerImpl.
     */
    private static var _forceLinkNDMI:NativeDragManagerImpl;

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

    /**
     *  Constructor.
     *  
     *  @langversion 3.0
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function WindowedApplication()
    {
        super();
        
        addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
        addEventListener(FlexEvent.PREINITIALIZE, preinitializeHandler);
        addEventListener(FlexEvent.UPDATE_COMPLETE, updateComplete_handler);
        addEventListener(FlexEvent.CREATION_COMPLETE, creationCompleteHandler);

        var nativeApplication:NativeApplication = NativeApplication.nativeApplication;
        nativeApplication.addEventListener(Event.ACTIVATE, nativeApplication_activateHandler);
        nativeApplication.addEventListener(Event.DEACTIVATE, nativeApplication_deactivateHandler);
        nativeApplication.addEventListener(Event.NETWORK_CHANGE, dispatchEvent);

        nativeApplication.addEventListener(InvokeEvent.INVOKE, nativeApplication_invokeHandler);
        initialInvokes = new Array();

        //Force DragManager to instantiate so that it can handle drags from
        //outside the app.
        DragManager.isDragging;
    }

    //--------------------------------------------------------------------------
    //
    //  Variables
    //
    //--------------------------------------------------------------------------

    /**
     * @private
     */
    private var _nativeWindow:NativeWindow;

    /**
     *  @private
     */
    private var _nativeWindowVisible:Boolean = true;
    
    /**
     *  @private
     */
    private var toMax:Boolean = false;

    /**
     *  @private
     */
    private var appViewMetrics:EdgeMetrics;

    /**
     *  @private
     */
    private var gripper:Button;

    /**
     *  @private
     */
    private var gripperHit:Sprite;

    /**
     *  @private
     */
    private var _gripperPadding:Number = 3;

    /**
     *  @private
     */
    private var initialInvokes:Array;

    /**
     *  @private
     */
    private var invokesPending:Boolean = true;

    /**
     *  @private
     */
    private var lastDisplayState:String = StageDisplayState.NORMAL;

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

    /**
     *  @private
     *  A reference to this Application's title bar skin.
     *  This is a child of the titleBar.
     */
    mx_internal var titleBarBackground:IFlexDisplayObject;

    /**
     *  @private
     *  A reference to this Application's status bar skin.
     *  This is a child of the statusBar.
     */
    mx_internal var statusBarBackground:IFlexDisplayObject;

    /**
    *  @private
    */
    private var oldX:Number;

    /**
    *  @private
    */
    private var oldY:Number;

    /**
     *  @private
     */
    private var prevX:Number;

    /**
     *  @private
     */
    private var prevY:Number;

    /**
     *  @private
     */
    private var windowBoundsChanged:Boolean = true;
    
    /**
     *  @private
     */
    private var prevActiveFrameRate:Number = -1;

    /**
     *  @private
     *  Determines whether the WindowedApplication opens in an active state.
     *  If you are opening up other windows at startup that should be active,
     *  this will ensure that the WindowedApplication does not steal focus.
     *
     *  @default true
     */
    private var activateOnOpen:Boolean = true;

    /**
     *  @private
     */
    private var ucCount:Number = 0;
        
    //--------------------------------------------------------------------------
    //
    //  Overridden properties: UIComponent
    //
    //--------------------------------------------------------------------------

    //----------------------------------
    //  height
    //----------------------------------

    [Bindable("heightChanged")]
    [Inspectable(category="General")]
    [PercentProxy("percentHeight")]

    /**
     *  @private
     */
    override public function get height():Number
    {
        return _bounds.height;
    }

    /**
     *  @private
     *  Also sets the stage's height.
     */
    override public function set height(value:Number):void
    {
        if (value < minHeight)
            value = minHeight;
        else if (value > maxHeight)
            value = maxHeight;

        _bounds.height = value;
        boundsChanged = true;

        invalidateProperties();
        invalidateSize();
        invalidateViewMetricsAndPadding();

        // the heightChanged event is dispatched in commitProperties instead of
        // here because it can change based on user-interaction with the window
        // size and _height is set in there so don't want to prematurely
        // dispatch here yet
    }

    //----------------------------------
    //  maxHeight
    //----------------------------------

    /**
     *  @private
     *  Storage for the maxHeight property.
     */
    private var _maxHeight:Number = 2880;
    
    /**
     *  @private
     *  Keeps track of whether maxHeight property changed so we can
     *  handle it in commitProperties.
     */
    private var maxHeightChanged:Boolean = false;

    [Bindable("maxHeightChanged")]
    [Bindable("windowComplete")]

    /**
     *  @private
     */
    override public function get maxHeight():Number
    {
        if (nativeWindow && !maxHeightChanged)
            return nativeWindow.maxSize.y - chromeHeight();
        else
            return _maxHeight;
    }

    /**
     *  @private
     *  Specifies the maximum height of the application's window.
     *  
     *  @default dependent on the operating system and the AIR systemChrome setting. 
     * 
     *  @langversion 3.0
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    override public function set maxHeight(value:Number):void
    {
        _maxHeight = value;
        maxHeightChanged = true;
        invalidateProperties();
    }

    //----------------------------------
    //  maxWidth
    //----------------------------------

    /**
     *  @private
     *  Storage for the maxWidth property.
     */
    private var _maxWidth:Number = 2880;
    
    /**
     *  @private
     *  Keeps track of whether maxWidth property changed so we can
     *  handle it in commitProperties.
     */
    private var maxWidthChanged:Boolean = false;

    [Bindable("maxWidthChanged")]
    [Bindable("windowComplete")]

    /**
     *  @private
     */
    override public function get maxWidth():Number
    {
        if (nativeWindow && !maxWidthChanged)
            return nativeWindow.maxSize.x - chromeWidth();
        else
            return _maxWidth;
    }

    /**
     *  @private
     *  Specifies the maximum width of the application's window.
     *  
     *  @default dependent on the operating system and the AIR systemChrome setting. 
     * 
     *  @langversion 3.0
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    override public function set maxWidth(value:Number):void
    {
        _maxWidth = value;
        maxWidthChanged = true;
        invalidateProperties();
    }

     //---------------------------------
     //  minHeight
     //---------------------------------

    /**
     *  @private
     */
    private var _minHeight:Number = 0;
    
    /**
     *  @private
     *  Keeps track of whether minHeight property changed so we can
     *  handle it in commitProperties.
     */
    private var minHeightChanged:Boolean = false;

    [Bindable("minHeightChanged")]
    [Bindable("windowComplete")]

    /**
     *  @private
     *  Specifies the minimum height of the application's window.
     *  
     *  @default dependent on the operating system and the AIR systemChrome setting. 
     *  
     *  @langversion 3.0
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    override public function get minHeight():Number
    {
        if (nativeWindow && !minHeightChanged)
            return nativeWindow.minSize.y - chromeHeight();
        else
            return _minHeight;
    }

    /**
     *  @private
     */
    override public function set minHeight(value:Number):void
    {
        _minHeight = value;
        minHeightChanged = true;
        invalidateProperties();
    }

     //---------------------------------
     //  minWidth
     //---------------------------------

    /**
     *  @private
     *  Storage for the minWidth property.
     */
    private var _minWidth:Number = 0;
    
   /**
     *  @private
     *  Keeps track of whether minWidth property changed so we can
     *  handle it in commitProperties.
     */
    private var minWidthChanged:Boolean = false;

    [Bindable("minWidthChanged")]
    [Bindable("windowComplete")]

    /**
     *  @private
     *  Specifies the minimum width of the application's window.
     *  
     *  @default dependent on the operating system and the AIR systemChrome setting. 
     *  
     *  @langversion 3.0
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    override public function get minWidth():Number
    {
        if (nativeWindow && !minWidthChanged)
            return nativeWindow.minSize.x - chromeWidth();
        else
            return _minWidth;
    }

    /**
     *  @private
     */
    override public function set minWidth(value:Number):void
    {
        _minWidth = value;
        minWidthChanged = true;
        invalidateProperties();
    }

    //----------------------------------
    //  visible
    //----------------------------------
    
    [Bindable("hide")]
    [Bindable("show")]
    [Bindable("windowComplete")]

    /**
     *  @private
     *  Also sets the NativeWindow's visibility.
     */ 
    override public function get visible():Boolean
    {
        if (nativeWindow && nativeWindow.closed)
            return false;
        if (nativeWindow)
            return nativeWindow.visible;
        else
            return _nativeWindowVisible;
    }

    /**
     *  @private
     */
    override public function set visible(value:Boolean):void
    {
        setVisible(value);
    }
    
    /**
     *  @private
     *  We override setVisible because there's the flash display object concept 
     *  of visibility and also the nativeWindow concept of visibility.
     */
    override public function setVisible(value:Boolean,
                                        noEvent:Boolean = false):void
    {
        // first handle the native window stuff
        if (!_nativeWindow)
        {
            _nativeWindowVisible = value;
            invalidateProperties();
        }
        else if (!_nativeWindow.closed)
        {
            if (value)
            {
                _nativeWindow.visible = value;
            }
            else
            {
                // in the conditions below we will play an effect
                if (getStyle("hideEffect") && initialized && $visible != value)
                    addEventListener(EffectEvent.EFFECT_END, hideEffectEndHandler);
                else
                    _nativeWindow.visible = value;
            }
        }
        
        // now call super.setVisible
        super.setVisible(value, noEvent);
    }

    //----------------------------------
    //  width
    //----------------------------------

    [Bindable("widthChanged")]
    [Inspectable(category="General")]
    [PercentProxy("percentWidth")]
    
    /**
     *  @private
     */
    override public function get width():Number
    {
        return _bounds.width;
    }

    /**
     *  @private
     *  Also sets the stage's width.
     */
     override public function set width(value:Number):void
     {
        if (value < minWidth)
            value = minWidth;
        else if (value > maxWidth)
            value = maxWidth;

        _bounds.width = value;
        boundsChanged = true;

        invalidateProperties();
        invalidateSize();
        invalidateViewMetricsAndPadding();

        // the widthChanged event is dispatched in commitProperties instead of
        // here because it can change based on user-interaction with the window
        // size and _width is set in there so don't want to prematurely
        // dispatch here yet
     }

    //--------------------------------------------------------------------------
    //
    //  Overridden properties: Container
    //
    //--------------------------------------------------------------------------

    //----------------------------------
    //  viewMetrics
    //----------------------------------

    /**
     *  @private
     */
    override public function get viewMetrics():EdgeMetrics
    {

        var bm:EdgeMetrics = super.viewMetrics;
        var vm:EdgeMetrics = new EdgeMetrics(bm.left, bm.top,
                                             bm.right, bm.bottom);


        // Since the header covers the solid portion of the border,
        // we need to use the larger of borderThickness or headerHeight

        if (showTitleBar)
        {
            var hHeight:Number = getHeaderHeight();
            if (!isNaN(hHeight))
                vm.top += hHeight;
        }

        if (_showStatusBar)
        {
            var sHeight:Number = getStatusBarHeight();
            if (!isNaN(sHeight))
                vm.bottom += sHeight;
        }

        return vm;
    }

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

    //----------------------------------
    //  applicationID
    //----------------------------------

    /**
     *  The identifier that AIR uses to identify the application.
     *  
     *  @langversion 3.0
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get applicationID():String
    {
        return nativeApplication.applicationID;
    }

    //----------------------------------
    //  alwaysInFront
    //----------------------------------

    /**
     *  @private
     *  Storage for the alwaysInFront property.
     */
    private var _alwaysInFront:Boolean = false;

    /**
     *  Determines whether the underlying NativeWindow is always in front of other windows.
     *
     *  @default false
     *  
     *  @langversion 3.0
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get alwaysInFront():Boolean
    {
        if (_nativeWindow && !_nativeWindow.closed)
            return nativeWindow.alwaysInFront;
        else
            return _alwaysInFront;
    }
    
    /**
     *  @private
     */
    public function set alwaysInFront(value:Boolean):void
    {
        _alwaysInFront = value;
        if (_nativeWindow && !_nativeWindow.closed)
            nativeWindow.alwaysInFront = value;
    }

    //----------------------------------
    //  autoExit
    //----------------------------------

    /**
     *  Specifies whether the AIR application will quit when the last
     *  window closes or will continue running in the background.
     *
     *  @default true
     *  
     *  @langversion 3.0
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get autoExit():Boolean
    {
        return nativeApplication.autoExit;
    }
    
    /**
     *  @private
     */
    public function set autoExit(value:Boolean):void
    {
        nativeApplication.autoExit = value;
    }

    //----------------------------------
    //  backgroundFrameRate
    //----------------------------------

    /**
     *  @private
     *  Storage for the backgroundFrameRate property.
     */
    private var _backgroundFrameRate:Number = -1;

    /**
     *  Specifies the frame rate to use when the application is inactive.
     *  When set to -1, no background frame rate throttling occurs.
     *
     *  @default -1
     *  
     *  @langversion 3.0
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public function get backgroundFrameRate():Number
    {
        return _backgroundFrameRate;
    }
   
    /**
     *  @private
     */ 
    public function set backgroundFrameRate(frameRate:Number):void
    {
        _backgroundFrameRate = frameRate;
    }
    
    //----------------------------------
    //  bounds
    //----------------------------------

    /**
     *  @private
     *  Storage for the bounds property.
     */
    private var _bounds:Rectangle = new Rectangle(0,0,0,0);

    /**
     *  @private
     */
    private var boundsChanged:Boolean = false;

    /**
     *  @private
     *  Storage for the height and width
     */
    protected function get bounds():Rectangle
    {
        return nativeWindow.bounds;
    }

    /**
     *  @private
     */
    protected function set bounds(value:Rectangle):void
    {
        nativeWindow.bounds = value;
        boundsChanged = true;

        invalidateProperties();
        invalidateSize();
        invalidateViewMetricsAndPadding();
    }

    //----------------------------------
    //  closed
    //----------------------------------

    /**
     *  Returns true when the underlying window has been closed.
     *  
     *  @langversion 3.0
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get closed():Boolean
    {
        return nativeWindow.closed;
    }

    //----------------------------------
    //  dockIconMenu
    //----------------------------------

    /**
     *  @private
     *  Storage for the dockIconMenu property.
     */
    private var _dockIconMenu:FlexNativeMenu;

    /**
     *  The dock icon menu. Some operating systems do not support dock icon menus.
     *  
     *  @langversion 3.0
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get dockIconMenu():FlexNativeMenu
    {
        return _dockIconMenu;
    }

    /**
     *  @private
     */
    public function set dockIconMenu(value:FlexNativeMenu):void
    {
        _dockIconMenu = value;

        if (NativeApplication.supportsDockIcon)
        {
            if (nativeApplication.icon is DockIcon)
                DockIcon(nativeApplication.icon).menu = value.nativeMenu;
        }
    }

    //----------------------------------
    //  maximizable
    //----------------------------------

    /**
     *  Specifies whether the window can be maximized.
     *  
     *  @langversion 3.0
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get maximizable():Boolean
    {
        if (!nativeWindow.closed)
            return nativeWindow.maximizable;
        else
            return false;
    }

    //----------------------------------
    //  minimizable
    //----------------------------------

    /**
     *  Specifies whether the window can be minimized.
     *  
     *  @langversion 3.0
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get minimizable():Boolean
    {
        if (!nativeWindow.closed)
            return nativeWindow.minimizable;
        else
            return false;
    }

    //----------------------------------
    //  menu
    //----------------------------------

    /**
     *  @private
     *  Storage for the menu property.
     */
    private var _menu:FlexNativeMenu;

    /**
     *  @private
     */
    private var menuChanged:Boolean = false;

    /**
     *  The application menu for operating systems that support an application menu,
     *  or the window menu of the application's initial window for operating
     *  systems that support window menus.
     *  
     *  @langversion 3.0
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get menu():FlexNativeMenu
    {
        return _menu;
    }

    /**
     *  @private
     */
    public function set menu(value:FlexNativeMenu):void
    {
        if (_menu)
        {
            _menu.automationParent = null;
            _menu.automationOwner = null;
        }
        
        _menu = value;
        menuChanged = true;
        
        if (_menu)
        {
            menu.automationParent = this;
            menu.automationOwner = this;
        }
    }

    //----------------------------------
    //  nativeWindow
    //----------------------------------

    /**
     *  The NativeWindow used by this WindowedApplication component (the initial
     *  native window of the application).
     *  
     *  @langversion 3.0
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get nativeWindow():NativeWindow
    {
        if ((systemManager != null) && (systemManager.stage != null))
            return systemManager.stage.nativeWindow;
    
        return null;
    }

    //---------------------------------
    //  resizable
    //---------------------------------

    /**
     *  Specifies whether the window can be resized.
     *  
     *  @langversion 3.0
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get resizable():Boolean
    {
        if (nativeWindow.closed)
            return false;
        return nativeWindow.resizable;
    }

    //----------------------------------
    //  nativeApplication
    //----------------------------------

    /**
     *  The NativeApplication object representing the AIR application.
     *  
     *  @langversion 3.0
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get nativeApplication():NativeApplication
    {
        return NativeApplication.nativeApplication;
    }

    //----------------------------------
    //  showGripper
    //----------------------------------

    /**
     *  @private
     *  Storage for the showGripper property.
     */
    private var _showGripper:Boolean = true;

    /**
     *  @private
     */
    private var showGripperChanged:Boolean = true;

    /**
     *  If <code>true</code>, the gripper is visible.
     *
     *  <p>On Mac OS X a window with <code>systemChrome</code>
     *  set to <code>"standard"</code>
     *  always has an operating system gripper, so this property is ignored
     *  in that case.</p>
     *
     *  @default true
     *  
     *  @langversion 3.0
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get showGripper():Boolean
    {
        return _showGripper;
    }

    /**
     *  @private
     */
    public function set showGripper(value:Boolean):void
    {
        if (_showGripper == value)
            return;

        _showGripper = value;
        showGripperChanged = true;

        invalidateProperties();
        invalidateDisplayList();
    }

     //---------------------------------
    //  showStatusBar
    //----------------------------------

    /**
     *  @private
     *  Storage for the showStatusBar property.
     */
    private var _showStatusBar:Boolean = true;

    /**
     *  @private
     */
    private var showStatusBarChanged:Boolean = true;

    /**
     *  If <code>true</code>, the status bar is visible.
     *
     *  @default true
     *  
     *  @langversion 3.0
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get showStatusBar():Boolean
    {
        return _showStatusBar;
    }

    /**
     *  @private
     */
    public function set showStatusBar(value:Boolean):void
    {
        if (_showStatusBar == value)
            return;

        _showStatusBar = value;
        showStatusBarChanged = true;

        invalidateProperties();
        invalidateDisplayList();
    }

    //----------------------------------
    //  showTitleBar
    //----------------------------------

    /**
     *  @private
     *  Storage for the showTitleBar property.
     */
    private var _showTitleBar:Boolean = true;

    /**
     *  @private
     */
    private var showTitleBarChanged:Boolean = true;

    /**
     *  If <code>true</code>, the window's title bar is visible.
     *
     *  @default true
     *  
     *  @langversion 3.0
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get showTitleBar():Boolean
    {
        return _showTitleBar;
    }

    /**
     *  @private
     */
    public function set showTitleBar(value:Boolean):void
    {
        if (_showTitleBar == value)
            return;

        _showTitleBar = value;
        showTitleBarChanged = true;

        invalidateProperties();
        invalidateDisplayList();
    }

    //----------------------------------
    //  status
    //----------------------------------

    /**
     *  @private
     *  Storage for the status property.
     */
    private var _status:String = "";

    /**
     *  @private
     */
    private var statusChanged:Boolean = false;

    [Bindable("statusChanged")]

    /**
     *  The string that appears in the status bar, if it is visible.
     *
     *  @default ""
     *  
     *  @langversion 3.0
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get status():String
    {
        return _status;
    }

    /**
     *  @private
     */
    public function set status(value:String):void
    {
        _status = value;
        statusChanged = true;

        invalidateProperties();
        invalidateSize();
        invalidateViewMetricsAndPadding();

        dispatchEvent(new Event("statusChanged"));
    }

    //----------------------------------
    //  statusBar
    //----------------------------------

    /**
     *  @private
     *  Storage for the statusBar property.
     */
    private var _statusBar:UIComponent;

    /**
     *  The UIComponent that displays the status bar.
     *  
     *  @langversion 3.0
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get statusBar():UIComponent
    {
        return _statusBar;
    }

    //----------------------------------
    //  statusBarFactory
    //----------------------------------
    
    /**
     *  @private
     *  Storage for the statusBarFactory property
     */
    private var _statusBarFactory:IFactory = new ClassFactory(StatusBar);
    
    /**
     *  @private
     */
    private var statusBarFactoryChanged:Boolean = false;
    
    [Bindable("statusBarFactoryChanged")]
    
    /**
     *  The IFactory that creates an instance to use
     *  as the status bar.
     *  The default value is an IFactory for StatusBar.
     *
     *  <p>If you write a custom status bar class, it should expose
     *  a public property named <code>status</code>.</p>
     *  
     *  @langversion 3.0
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get statusBarFactory():IFactory
    {
        return _statusBarFactory;
    }

    /**
     *  @private
     */
    public function set statusBarFactory(value:IFactory):void
    {
        _statusBarFactory = value;
        statusBarFactoryChanged = true;

        invalidateProperties();

        dispatchEvent(new Event("statusBarFactoryChanged"));
    }

    //----------------------------------
    //  statusBarStyleFilters
    //----------------------------------

    private static var _statusBarStyleFilters:Object =
    {
        "statusBarBackgroundColor" : "statusBarBackgroundColor",
        "statusBarBackgroundSkin" : "statusBarBackgroundSkin",
        "statusTextStyleName" : "statusTextStyleName"
    };

    /**
     *  Set of styles to pass from the WindowedApplication to the status bar.
     *
     *  @see mx.styles.StyleProxy
     *  
     *  @langversion 3.0
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    protected function get statusBarStyleFilters():Object
    {
        return _statusBarStyleFilters;
    }

    //----------------------------------
    //  systemChrome
    //----------------------------------

    private var _systemChrome:String = NativeWindowSystemChrome.STANDARD;
    
    /**
     *  Specifies the type of system chrome (if any) the window has.
     *  The set of possible values is defined by the constants
     *  in the NativeWindowSystemChrome class.
     *
     *  @see flash.display.NativeWindow#systemChrome
     *  
     *  @langversion 3.0
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get systemChrome():String
    {
        return _systemChrome;
    }

    //----------------------------------
    //  systemTrayIconMenu
    //----------------------------------

    /**
     *  @private
     *  Storage for the systemTrayIconMenu property.
     */
    private var _systemTrayIconMenu:FlexNativeMenu;

    /**
     *  The system tray icon menu. Some operating systems do not support system tray icon menus.
     *  
     *  @langversion 3.0
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get systemTrayIconMenu():FlexNativeMenu
    {
        return _systemTrayIconMenu;
    }

    /**
     *  @private
     */
    public function set systemTrayIconMenu(value:FlexNativeMenu):void
    {
        _systemTrayIconMenu = value;

        if (NativeApplication.supportsSystemTrayIcon)
        {
            if (nativeApplication.icon is SystemTrayIcon)
                SystemTrayIcon(nativeApplication.icon).menu = value.nativeMenu;
        }
    }

    //----------------------------------
    //  title
    //----------------------------------

    /**
     *  @private
     *  Storage for the title property.
     */
    private var _title:String = "";

    /**
     *  @private
     */
    private var titleChanged:Boolean = false;

    [Bindable("titleChanged")]

    /**
     *  The title that appears in the window title bar and
     *  the taskbar.
     *
     *  If you are using system chrome and you set this property to something
     *  different than the &lt;title&gt; tag in your application.xml,
     *  you may see the title from the XML file appear briefly first.
     *
     *  @default ""
     *  
     *  @langversion 3.0
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get title():String
    {
        return _title;
    }
    /**
     *  @private
     */
    public function set title(value:String):void
    {
        _title = value;
        titleChanged = true;

        invalidateProperties();
        invalidateSize();
        invalidateViewMetricsAndPadding();
        invalidateDisplayList();

        dispatchEvent(new Event("titleChanged"));
    }

    //----------------------------------
    //  titleBar
    //----------------------------------

    /**
     *  @private
     *  Storage for the titleBar property.
     */
    private var _titleBar:UIComponent;

    /**
     *  The UIComponent that displays the title bar.
     *  
     *  @langversion 3.0
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get titleBar():UIComponent
    {
        return _titleBar;
    }

    //----------------------------------
    //  titleBarFactory
    //----------------------------------
    
    /**
     *  @private
     *  Storage for the titleBarFactory property
     */
    private var _titleBarFactory:IFactory = new ClassFactory(TitleBar);
    
    /**
     *  @private
     */
    private var titleBarFactoryChanged:Boolean = false;
        
    [Bindable("titleBarFactoryChanged")]
    
    /**
     *  The IFactory that creates an instance to use
     *  as the title bar.
     *  The default value is an IFactory for TitleBar.
     *
     *  <p>If you write a custom title bar class, it should expose
     *  public properties named <code>titleIcon</code>
     *  and <code>title</code>.</p>
     *  
     *  @langversion 3.0
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get titleBarFactory():IFactory
    {
        return _titleBarFactory;
    }

    /**
     *  @private
     */
    public function set titleBarFactory(value:IFactory):void
    {
        _titleBarFactory = value;
        titleBarFactoryChanged = true;

        invalidateProperties();

        dispatchEvent(new Event("titleBarFactoryChanged"));
    }

    //----------------------------------
    //  titleBarStyleFilters
    //----------------------------------

    private static var _titleBarStyleFilters:Object =
    {
        "buttonAlignment" : "buttonAlignment",
        "buttonPadding" : "buttonPadding",
        "closeButtonSkin" : "closeButtonSkin",
        "cornerRadius" : "cornerRadius",
        "headerHeight" : "headerHeight",
        "maximizeButtonSkin" : "maximizeButtonSkin",
        "minimizeButtonSkin" : "minimizeButtonSkin",
        "restoreButtonSkin" : "restoreButtonSkin",
        "titleAlignment" : "titleAlignment",
        "titleBarBackgroundSkin" : "titleBarBackgroundSkin",
        "titleBarButtonPadding" : "titleBarButtonPadding",
        "titleBarColors" : "titleBarColors",
        "titleTextStyleName" : "titleTextStyleName"
    };

    /**
     *  Set of styles to pass from the WindowedApplication to the titleBar.
     *  @see mx.styles.StyleProxy
     *  
     *  @langversion 3.0
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    protected function get titleBarStyleFilters():Object
    {
        return _titleBarStyleFilters;
    }

    //----------------------------------
    //  titleIcon
    //----------------------------------

    /**
     *  @private
     *  A reference to this container's title icon.
     */
    private var _titleIcon:Class;

    /**
     *  @private
     */
    private var titleIconChanged:Boolean = false;
        
    [Bindable("titleIconChanged")]

    /**
     *  The Class (usually an image) used to draw the title bar icon.
     *
     *  @default null
     *  
     *  @langversion 3.0
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get titleIcon():Class
    {
        return _titleIcon;
    }

    /**
     *  @private
     */
    public function set titleIcon(value:Class):void
    {
        _titleIcon = value;
        titleIconChanged = true;

        invalidateProperties();
        invalidateSize();
        invalidateViewMetricsAndPadding();
        invalidateDisplayList();

        dispatchEvent(new Event("titleIconChanged"));
    }

    //----------------------------------
    //  transparent
    //----------------------------------

    /**
     *  Specifies whether the window is transparent.
     *  
     *  @langversion 3.0
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get transparent():Boolean
    {
        if (nativeWindow.closed)
            return false;
        return nativeWindow.transparent;
    }

    //----------------------------------
    //  type
    //----------------------------------

    /**
     *  Specifies the type of NativeWindow that this component
     *  represents. The set of possible values is defined by the constants
     *  in the NativeWindowType class.
     *
     *  @see flash.display.NativeWindowType
     *  
     *  @langversion 3.0
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get type():String
    {
        return NativeWindowType.NORMAL;
    }

    //----------------------------------
    //  useNativeDragManager
    //----------------------------------
    
    [Inspectable(defaultValue="true")]
    
    /**
     *  If <code>true</code>, the DragManager should use the NativeDragManagerImpl implementation class.
     *  If <code>false</code>, then the DragManagerImpl class will be used. 
     *   
     *  <p>Note: This property cannot be set by ActionScript code; it must be set in MXML code.
     *  That means you cannot change its value at run time.</p>
     *
     *  <p>By default, the DragManager  for AIR applications built in Flex uses the 
     *  NativeDragManagerImpl class as the implementation class. 
     *  Flash Player applications build in Flex use the DragManagerImpl class. </p>
     *
     *  <p>The NativeDragManagerImpl class is a bridge between the AIR NativeDragManager API 
     *  and the Flex DragManager API. 
     *  The AIR NativeDragManager class uses the operating system's drag and drop APIs. 
     *  It supports dragging between AIR windows and between the operating system and AIR. 
     *  Because the operating system controls the drag-and-drop operation, 
     *  it is not possible to customize the cursors during a drag. 
     *  Also, you have no control over the drop animation. 
     *  The behavior is dependent upon the operating system and has some inconsistencies across different platforms.</p>
     *
     *  <p>The DragManagerImpl class does not use the operating system for drag-and-drop. 
     *  Instead, it controls the entire drag-and-drop process. 
     *  It supports customizing the cursors and provides a drop animation. 
     *  However, it does not allow dragging between AIR windows and between the operating system or AIR window.</p>
     *
     *  @default true
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    
    /*  This property is not directly read by the systemManager. It is here so that it gets 
    *  picked up by the compiler and included in the info() structure 
    *  for the generated system manager.  */
    public var useNativeDragManager:Boolean = true;
    
    //--------------------------------------------------------------------------
    //
    //  Overridden methods: UIComponent
    //
    //--------------------------------------------------------------------------

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

        if (getStyle("showFlexChrome") == false ||
            getStyle("showFlexChrome") == "false")
        {
            setStyle("borderStyle", "none");
            setStyle("backgroundAlpha", 0);
            return;
        }

        if (!_statusBar)
        {
            _statusBar = statusBarFactory.newInstance();
            _statusBar.styleName = new StyleProxy(this, statusBarStyleFilters);
            rawChildren.addChild(DisplayObject(_statusBar));
            showStatusBarChanged = true;
            statusBarFactoryChanged = false;
        }

        if (systemManager.stage.nativeWindow.systemChrome != "none")
        {
            setStyle("borderStyle", "none");
            return;
        }

        if (!_titleBar)
        {
            _titleBar = titleBarFactory.newInstance();
            _titleBar.styleName = new StyleProxy(this, titleBarStyleFilters);
            rawChildren.addChild(DisplayObject(titleBar));
            showTitleBarChanged = true;
            titleBarFactoryChanged = false;
        }

        if (!gripper)
        {
            gripper = new Button();
            var gripSkin:String = getStyle("gripperStyleName");
            if (gripSkin)
            {
                var tmp:CSSStyleDeclaration =
                    styleManager.getStyleDeclaration("." + gripSkin);
                gripper.styleName = gripSkin;
            }
            gripper.skinLayoutDirection = undefined;
            
            rawChildren.addChild(gripper);

            gripperHit = new Sprite();
            gripperHit.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
            rawChildren.addChild(gripperHit);
        }
    }

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

        // AIR won't allow you to set the min width greater than the current 
        // max width (same is true for height). You also can't set the max 
        // width less than the current min width (same is true for height).
        // This makes the updating of the new minSize and maxSize a bit tricky.
        if (minWidthChanged || minHeightChanged || maxWidthChanged || maxHeightChanged)
        {
            var minSize:Point = nativeWindow.minSize;
            var maxSize:Point = nativeWindow.maxSize;
            var newMinWidth:Number  = minWidthChanged  ? _minWidth  + chromeWidth()  : minSize.x;
            var newMinHeight:Number = minHeightChanged ? _minHeight + chromeHeight() : minSize.y;
            var newMaxWidth:Number  = maxWidthChanged  ? _maxWidth  + chromeWidth()  : maxSize.x;
            var newMaxHeight:Number = maxHeightChanged ? _maxHeight + chromeHeight() : maxSize.y;
            
            if (minWidthChanged || minHeightChanged)
            {
                // If the new min size is greater than the old max size, then
                // we need to set the new max size now.
                if ((maxWidthChanged && newMinWidth > minSize.x) || 
                    (maxHeightChanged && newMinHeight > minSize.y))
                {
                    nativeWindow.maxSize = new Point(newMaxWidth, newMaxHeight);
                }
                
                nativeWindow.minSize = new Point(newMinWidth, newMinHeight);
            }
            
            // Set the max width or height if it is not already set. The max 
            // width and height could have been set above when setting minSize
            // but the max size would have been rejected by AIR if it were less
            // than the old min size.
            if (newMaxWidth != maxSize.x || newMaxHeight != maxSize.y)
                nativeWindow.maxSize = new Point(newMaxWidth, newMaxHeight);
        }
        
        // minimum width and height
        if (minWidthChanged || minHeightChanged)
        {
            if (minWidthChanged)
            {
                minWidthChanged = false;
                if (width < minWidth)
                    width = minWidth;
                dispatchEvent(new Event("minWidthChanged"));
            }
            if (minHeightChanged)
            {
                minHeightChanged = false;
                if (height < minHeight)
                    height = minHeight;
                dispatchEvent(new Event("minHeightChanged"));
            }
        }
        
        // maximum width and height
        if (maxWidthChanged || maxHeightChanged)
        {
            windowBoundsChanged = true;
            
            if (maxWidthChanged)
            {
                maxWidthChanged = false;
                if (width > maxWidth)
                    width = maxWidth;
                dispatchEvent(new Event("maxWidthChanged"));
            }
            if (maxHeightChanged)
            {
                maxHeightChanged = false;
                if (height > maxHeight)
                    height = maxHeight;
                dispatchEvent(new Event("maxHeightChanged"));
            }
        }

        if (boundsChanged)
        {       
            // Work around an AIR issue setting the stageHeight to zero when 
            // using system chrome. The set of the stage.stageHeight property
            // is rejected unless the nativeWindow is first set to the proper height. 
            // Don't perform this workaround if the window has zero height due 
            // to being minimized. Setting the nativeWindow height to non-zero 
            // causes AIR to restore the window.
            if (_bounds.height == 0 && 
                nativeWindow.displayState != NativeWindowDisplayState.MINIMIZED &&
                systemChrome == NativeWindowSystemChrome.STANDARD)
                nativeWindow.height = chromeHeight() + _bounds.height;

            systemManager.stage.stageWidth = _bounds.width;
            systemManager.stage.stageHeight = _bounds.height;

            // Set _width and _height.  This will update the mirroring
            // transform if applicable.
            setActualSize(_bounds.width, _bounds.height);
            
            boundsChanged = false;
        }

        if (windowBoundsChanged)
        {
            _bounds.width = systemManager.stage.stageWidth;
            _bounds.height = systemManager.stage.stageHeight;

            // Set _width and _height.  This will update the mirroring
            // transform if applicable.
            setActualSize(_bounds.width, _bounds.height);
            
            windowBoundsChanged = false;
        }

        if (menuChanged && !nativeWindow.closed)
        {
            menuChanged = false;
            
            if (menu == null)
            {
                if (NativeApplication.supportsMenu)
                    nativeApplication.menu = null;
                else if (NativeWindow.supportsMenu)
                    nativeWindow.menu = null;
            }
            else if (menu.nativeMenu)
            {
                if (NativeApplication.supportsMenu)
                    nativeApplication.menu = menu.nativeMenu;
                else if (NativeWindow.supportsMenu)
                    nativeWindow.menu = menu.nativeMenu;
            }
            
            dispatchEvent(new Event("menuChanged"));
        }

        if (titleBarFactoryChanged)
        {
            if (_titleBar)
            {
                // Remove old titleBar.
                rawChildren.removeChild(DisplayObject(titleBar));
                _titleBar = null;
            }
            _titleBar = titleBarFactory.newInstance();
            _titleBar.styleName = new StyleProxy(this, titleBarStyleFilters);
             rawChildren.addChild(DisplayObject(titleBar));
            titleBarFactoryChanged = false;
            invalidateDisplayList();
        }

        if (showTitleBarChanged)
        {
            if (titleBar)
                titleBar.visible = _showTitleBar;
            showTitleBarChanged = false;
        }

        if (titleIconChanged)
        {
            if (_titleBar && "titleIcon" in _titleBar)
                _titleBar["titleIcon"] = _titleIcon;
            titleIconChanged = false;
        }

        if (titleChanged)
        {
            if (!nativeWindow.closed)
                systemManager.stage.nativeWindow.title = _title;
            if (_titleBar && "title" in _titleBar)
                _titleBar["title"] = _title;
            titleChanged = false;
        }

        if (statusBarFactoryChanged)
        {
            if (_statusBar)
            {
                // Remove old statusBar.
                rawChildren.removeChild(DisplayObject(_statusBar));
                _statusBar = null
            }
            _statusBar = statusBarFactory.newInstance();
            _statusBar.styleName = new StyleProxy(this, statusBarStyleFilters);

            // Add it underneath the gripper.
            rawChildren.addChild(DisplayObject(_statusBar));
            if (gripper)
            {
                var gripperIndex:int = rawChildren.getChildIndex(DisplayObject(gripper)); 
                rawChildren.setChildIndex(DisplayObject(_statusBar), gripperIndex);
            }
            statusBarFactoryChanged = false;
            showStatusBarChanged = true;
            statusChanged = true;
            invalidateDisplayList();
        }

        if (showStatusBarChanged)
        {
            if (_statusBar)
                _statusBar.visible = _showStatusBar;
            showStatusBarChanged = false;
        }

        if (statusChanged)
        {
            if (_statusBar && "status" in _statusBar)
                _statusBar["status"] = _status;
            statusChanged = false;
        }

        if (showGripperChanged)
        {
            if (gripper)
            {
                gripper.visible = _showGripper;
                gripperHit.visible = _showGripper;
            }
            showGripperChanged = false;
        }

        if (toMax)
        {
            toMax = false;
            if (!nativeWindow.closed)
                nativeWindow.maximize();
        }
     }

    /**
     *  @private
     */
    override public function initialize():void
    {
        // initialize _nativeWindow as soon as possible and
        // get the value of systemChrome.
        _nativeWindow = systemManager.stage.nativeWindow;
        _systemChrome = _nativeWindow.systemChrome;
        
        super.initialize();
    }

    /**
     *  @private
     */
    override public function validateDisplayList():void
    {
        super.validateDisplayList();
        if (!nativeWindow.closed)
        {
            if (Capabilities.os.substring(0, 3) == "Mac" && systemChrome == "standard")
            {
                //need to move the scroll bars to not overlap the systemChrome gripper
                //if both scrollbars are already visible, this has been done for us
                if ((horizontalScrollBar || verticalScrollBar) && !(horizontalScrollBar && verticalScrollBar) && !showStatusBar)
                {
                    if (!whiteBox)
                    {
                        whiteBox = new FlexShape();
                        whiteBox.name = "whiteBox";
        
                        var g:Graphics = whiteBox.graphics;
                        g.beginFill(0xFFFFFF);
                        g.drawRect(0, 0, verticalScrollBar ? verticalScrollBar.minWidth : 15, horizontalScrollBar ? horizontalScrollBar.minHeight : 15);
                        g.endFill()
        
                        rawChildren.addChild(whiteBox);
                    }
                    whiteBox.visible = true;
                    
                
                    if (horizontalScrollBar)
                    {
                        horizontalScrollBar.setActualSize(
                            horizontalScrollBar.width - whiteBox.width,
                            horizontalScrollBar.height);
                    }
                    if (verticalScrollBar)
                    {
                        verticalScrollBar.setActualSize(
                            verticalScrollBar.width,
                            verticalScrollBar.height - whiteBox.height);
                    }
                    whiteBox.x = systemManager.stage.stageWidth - whiteBox.width;
                    whiteBox.y = systemManager.stage.stageHeight - whiteBox.height;
                }
                else if (!(horizontalScrollBar && verticalScrollBar))
                {
                    if (whiteBox)
                    {
                        rawChildren.removeChild(whiteBox);
                        whiteBox = null;
                    }
                }
            }
            else if (gripper && showGripper && !showStatusBar)
            {
                //see if there are both scrollbars
                if (whiteBox)
                {
                    whiteBox.visible = false;
                    //if gripper + padding > whiteBox size, we need to move scrollbars
                    //this is, um, generally non-optimal looking
                    if (gripperHit.height > whiteBox.height)
                        verticalScrollBar.setActualSize(verticalScrollBar.width,
                            verticalScrollBar.height - (gripperHit.height - whiteBox.height));
                    if (gripperHit.width > whiteBox.width)
                        horizontalScrollBar.setActualSize(
                                horizontalScrollBar.width - (gripperHit.width  - whiteBox.height),
                                horizontalScrollBar.height);
                }
                else if (horizontalScrollBar)
                {
                    horizontalScrollBar.setActualSize(
                        horizontalScrollBar.width - gripperHit.width,
                        horizontalScrollBar.height);
                }
                else if (verticalScrollBar)
                {
                    verticalScrollBar.setActualSize(
                        verticalScrollBar.width,
                        verticalScrollBar.height - gripperHit.height);
                }
            }
            else if (whiteBox)//if there's no gripper, we need to show the white box, if appropriate
                whiteBox.visible = true;
        }
    }

    /**
     *  @private
     */
    override protected function updateDisplayList(unscaledWidth:Number,
                                                  unscaledHeight:Number):void
    {
        if (!nativeWindow.closed)
        {
            super.updateDisplayList(unscaledWidth, unscaledHeight);
    
            var bm:EdgeMetrics = borderMetrics;
                
            var leftOffset:Number = 10;
            var rightOffset:Number = 10;
    
            if (_statusBar)
            {
                _statusBar.move(bm.left, unscaledHeight - bm.bottom - getStatusBarHeight());
                _statusBar.setActualSize(unscaledWidth - bm.left - bm.right, getStatusBarHeight());
    
            }
    
            if (systemManager.stage.nativeWindow.systemChrome != "none" || systemManager.stage.nativeWindow.closed)
                return;
    
            var buttonAlign:String =
                String(getStyle("buttonAlignment"));
            if (titleBar)
            {
                titleBar.move(bm.left, bm.top);
                titleBar.setActualSize(unscaledWidth - bm.left - bm.right,
                                       getHeaderHeight());
            }
            if (titleBar && controlBar)
                controlBar.move(0, titleBar.height);
            if (gripper && showGripper)
            {
                _gripperPadding = getStyle("gripperPadding");
                gripper.setActualSize(gripper.measuredWidth,
                                        gripper.measuredHeight);
                gripperHit.graphics.beginFill(0xffffff, .0001);
                gripperHit.graphics.drawRect(0, 0, gripper.width + (2 * _gripperPadding), gripper.height + (2 * _gripperPadding));
                gripper.move(unscaledWidth - gripper.measuredWidth - _gripperPadding,
                            unscaledHeight - gripper.measuredHeight - _gripperPadding);
                gripperHit.x = gripper.x - _gripperPadding;
                gripperHit.y = gripper.y - _gripperPadding;
            }
        }
    }

    /**
     *  @private
     */
    override public function styleChanged(styleProp:String):void
    {
        super.styleChanged(styleProp);
        if (!nativeWindow.closed)
        {
            if (!(getStyle("showFlexChrome") == "false" || getStyle("showFlexChrome") == false))
            {
                if (styleProp == null || styleProp == "headerHeight" || styleProp == "gripperPadding")
                {
                    invalidateViewMetricsAndPadding();
                    invalidateDisplayList();
                    invalidateSize();
                }
            }
        }
    }

    /**
     *  @private
     */
    override public function move(x:Number, y:Number):void
    {
        if (nativeWindow && !nativeWindow.closed)
        {
            var tmp:Rectangle = nativeWindow.bounds;
            tmp.x = x;
            tmp.y = y;
            nativeWindow.bounds = tmp;
        }
    }

    /**
     *  @private
     *  Called when the "View Source" item in the application's context menu
     *  is selected.
     *
     *  Opens the window where AIR decides, sized to the parent application.
     *  It will close when the parent WindowedApplication closes.
     */
    override protected function menuItemSelectHandler(event:Event):void
    {
        const vsLoc:File = File.applicationDirectory.resolvePath(viewSourceURL);
        if (vsLoc.exists)
        {
            const screenRect:Rectangle = flash.display.Screen.mainScreen.visibleBounds;
            const screenWidth:int = screenRect.width;
            const screenHeight:int = screenRect.height;

            // roughly golden-ratio based on 90% of the smaller screen dimension
            // should be pleasing to the eye...
            const minDim:Number = Math.min(screenWidth, screenHeight);
            const winWidth:int = minDim * 0.9;
            const winHeight:int = winWidth * 0.618;
            
            const winX:int = (screenWidth - winWidth) / 2;
            const winY:int = (screenHeight - winHeight) / 2;
            
            const html:HTML = new HTML();
            {
                html.width  = winWidth;
                html.height = winHeight;
                html.location = vsLoc.url;
            }
    
            const win:Window = new Window();
            {
                win.type = NativeWindowType.UTILITY;
                win.systemChrome = NativeWindowSystemChrome.STANDARD;
                
                win.title = resourceManager.getString("core", "viewSource");
                
                win.width  = winWidth;
                win.height = winHeight;
                
                win.addChild(html);
                
                // handle resizing since the HTML should take the whole stage
                win.addEventListener(
                    FlexNativeWindowBoundsEvent.WINDOW_RESIZE,
                    viewSourceResizeHandler(html),
                    false, 0, true);

                // links should open in the system web browser (e.g. the .zip links)
                html.htmlLoader.navigateInSystemBrowser = true;
                
                // close the View Source window when this WindowedApp closes
                addEventListener(Event.CLOSING, viewSourceCloseHandler(win), false, 0, true);
            }
            
            // make it so
            win.open();
            win.move(winX, winY);
        }
        else
        {
            Alert.show(resourceManager.getString("core", "badFile"));
        }
    }

    //--------------------------------------------------------------------------
    //
    //  Methods
    //
    //--------------------------------------------------------------------------
    
    /**
     *  Activates the underlying NativeWindow (even if this application is not the active one).
     *  
     *  @langversion 3.0
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function activate():void
    {
        if (!systemManager.stage.nativeWindow.closed)
        {
            systemManager.stage.nativeWindow.activate();    
            
            // activate makes the native window visible so this 
            // component should become visible as well.
            visible = true;             
        }
    }

    /**
     *  Closes the application's NativeWindow (the initial native window opened by the application). This action is cancelable.
     *  
     *  @langversion 3.0
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function close():void
    {
        if (!nativeWindow.closed)
        {
            var e:Event = new Event("closing", true, true);
            stage.nativeWindow.dispatchEvent(e);
            if (!e.isDefaultPrevented())
                stage.nativeWindow.close();
        }
    }

    /**
     *  Closes the window and exits the application.
     *  
     *  @langversion 3.0
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function exit():void
    {
        nativeApplication.exit();
    }

    /**
     *  @private
     *  Returns the height of the header.
     */
    private function getHeaderHeight():Number
    {
        if (!nativeWindow.closed)
        {
            if (getStyle("headerHeight") != null)
                return getStyle("headerHeight");
            if (systemManager.stage.nativeWindow.systemChrome != "none")
                return 0;
            if (titleBar)
                return(titleBar.getExplicitOrMeasuredHeight());
        }
        return 0;
    }

    /**
     *  @private
     *  Returns the height of the statusBar.
     */
    public function getStatusBarHeight():Number
    {
        if (_statusBar)
            return _statusBar.getExplicitOrMeasuredHeight();

        return 0;
    }

    /**
     *  Maximizes the window, or does nothing if it's already maximized.
     *  
     *  @langversion 3.0
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function maximize():void
    {
        
        if (!nativeWindow || !nativeWindow.maximizable || nativeWindow.closed)
            return;
        if (systemManager.stage.nativeWindow.displayState!= NativeWindowDisplayState.MAXIMIZED)
        {
            var f:NativeWindowDisplayStateEvent = new NativeWindowDisplayStateEvent(
                        NativeWindowDisplayStateEvent.DISPLAY_STATE_CHANGING,
                        false, true, systemManager.stage.nativeWindow.displayState,
                        NativeWindowDisplayState.MAXIMIZED);
            systemManager.stage.nativeWindow.dispatchEvent(f);
            if (!f.isDefaultPrevented())
            {
                invalidateProperties();
                invalidateSize();
                invalidateDisplayList();
                toMax = true;
            }
        }
    }

    /**
     *  Minimizes the window.
     *  
     *  @langversion 3.0
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function minimize():void
    {
        if (!minimizable)
            return;
            
        if (!nativeWindow.closed)
        {
            var e:NativeWindowDisplayStateEvent = new NativeWindowDisplayStateEvent(
                    NativeWindowDisplayStateEvent.DISPLAY_STATE_CHANGING,
                    false, true, nativeWindow.displayState,
                    NativeWindowDisplayState.MINIMIZED)
            stage.nativeWindow.dispatchEvent(e);
            if (!e.isDefaultPrevented())
                stage.nativeWindow.minimize();
        }
    }

    /**
     *  Restores the window (unmaximizes it if it's maximized, or
     *  unminimizes it if it's minimized).
     *  
     *  @langversion 3.0
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function restore():void
    {
        if (!nativeWindow.closed)
        {
            var e:NativeWindowDisplayStateEvent;
            if (stage.nativeWindow.displayState == NativeWindowDisplayState.MAXIMIZED)
            {
                e = new NativeWindowDisplayStateEvent(
                            NativeWindowDisplayStateEvent.DISPLAY_STATE_CHANGING,
                            false, true, NativeWindowDisplayState.MAXIMIZED,
                            NativeWindowDisplayState.NORMAL);
                stage.nativeWindow.dispatchEvent(e);
                if (!e.isDefaultPrevented())
                    nativeWindow.restore();
            }
            else if (stage.nativeWindow.displayState == NativeWindowDisplayState.MINIMIZED)
            {
                e = new NativeWindowDisplayStateEvent(
                    NativeWindowDisplayStateEvent.DISPLAY_STATE_CHANGING,
                    false, true, NativeWindowDisplayState.MINIMIZED,
                    NativeWindowDisplayState.NORMAL);
                stage.nativeWindow.dispatchEvent(e);
                if (!e.isDefaultPrevented())
                    nativeWindow.restore();
            }
        }
    }

    /**
     *  Orders the window just behind another. To order the window behind
     *  a NativeWindow that does not implement IWindow, use this window's
     *  NativeWindow's <code>orderInBackOf()</code> method.
     *
     *  @param window The IWindow (Window or WindowedAplication)
     *  to order this window behind.
     *
     *  @return <code>true</code> if the window was succesfully sent behind;
     *  <code>false</code> if the window is invisible or minimized.
     *  
     *  @langversion 3.0
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
     public function orderInBackOf(window:IWindow):Boolean
     {
        if (nativeWindow && !nativeWindow.closed)
            return nativeWindow.orderInBackOf(window.nativeWindow);
        else
            return false;
     }

    /**
     *  Orders the window just in front of another. To order the window
     *  in front of a NativeWindow that does not implement IWindow, use this
     *  window's NativeWindow's <code>orderInFrontOf()</code> method.
     *
     *  @param window The IWindow (Window or WindowedAplication)
     *  to order this window in front of.
     *
     *  @return <code>true</code> if the window was succesfully sent in front;
     *  <code>false</code> if the window is invisible or minimized.
     *  
     *  @langversion 3.0
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
     public function orderInFrontOf(window:IWindow):Boolean
     {
        if (nativeWindow && !nativeWindow.closed)
            return nativeWindow.orderInFrontOf(window.nativeWindow);
        else
            return false;
     }

     /**
      *  Orders the window behind all others in the same application.
      *
      *  @return <code>true</code> if the window was succesfully sent to the back;
      *  <code>false</code> if the window is invisible or minimized.
      *  
      *  @langversion 3.0
      *  @playerversion AIR 1.1
      *  @productversion Flex 3
      */
     public function orderToBack():Boolean
     {
        if (nativeWindow && !nativeWindow.closed)
            return nativeWindow.orderToBack();
        else
            return false;
     }

 /**
  *  Orders the window in front of all others in the same application.
  *
  *  @return <code>true</code> if the window was succesfully sent to the front;
  *  <code>false</code> if the window is invisible or minimized.
  *  
  *  @langversion 3.0
  *  @playerversion AIR 1.1
  *  @productversion Flex 3
  */
     public function orderToFront():Boolean
     {
        if (nativeWindow && !nativeWindow.closed)
            return nativeWindow.orderToFront();
        else
            return false;
     }
     
    /**
     *  @private
     *  Returns the width of the chrome for the window
     */
    private function chromeWidth():Number
    {
        return nativeWindow.width - systemManager.stage.stageWidth;
    }
    
    /**
     *  @private
     *  Returns the height of the chrome for the window
     */
    private function chromeHeight():Number
    {
        return nativeWindow.height - systemManager.stage.stageHeight;
    }
        
    /**
     *  @private
     *  Starts a system move.
     */
    private function startMove(event:MouseEvent):void
    {
        addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
        addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);

        prevX = event.stageX;
        prevY = event.stageY;
    }

    /**
     *  @private
     *  Starts a system resize.
     */
    protected function startResize(start:String):void
    {
        if (!nativeWindow.closed)
            if (nativeWindow.resizable)
                stage.nativeWindow.startResize(start);
    }

    //--------------------------------------------------------------------------
    //
    //  Event handlers
    //
    //--------------------------------------------------------------------------
    
    /**
     *  @private
     */
    private function creationCompleteHandler(event:Event):void
    {
        addEventListener(Event.ENTER_FRAME, enterFrameHandler);
    }
    
    /**
     *  @private
     */
    private function enterFrameHandler(e:Event):void
    {
        if (!stage)
            return;
            
        removeEventListener(Event.ENTER_FRAME, enterFrameHandler);

        // If nativeApplication.nativeApplication.exit() has been called,
        // the window will already be closed.
        if (stage.nativeWindow.closed)
            return;

        //window properties that have been stored till window exists
        //now get applied to window
        stage.nativeWindow.visible = _nativeWindowVisible;
        dispatchEvent(new AIREvent(AIREvent.WINDOW_COMPLETE));
        
        // Now let any invoke events received from nativeApplication
        // during initialization, flow to our listeners.
        dispatchPendingInvokes();
        
        if (_nativeWindowVisible && activateOnOpen)
            stage.nativeWindow.activate();
        stage.nativeWindow.alwaysInFront = _alwaysInFront;
    }

    /**
     *  @private
     */
    private function dispatchPendingInvokes():void
    {
        invokesPending = false;
        for each (var event:InvokeEvent in initialInvokes)
            dispatchEvent(event);
        initialInvokes = null;
    }
    
    /**
     *  @private
     */
    private function hideEffectEndHandler(event:Event):void
    {
        if (!_nativeWindow.closed)
            _nativeWindow.visible = false;
        removeEventListener(EffectEvent.EFFECT_END, hideEffectEndHandler);
    }

    /**
     *  @private
     */
    private function windowMinimizeHandler(event:Event):void
    {
        if (!nativeWindow.closed)
            stage.nativeWindow.minimize();
        removeEventListener(EffectEvent.EFFECT_END, windowMinimizeHandler);
    }

    /**
     *  @private
     */
    private function windowUnminimizeHandler(event:Event):void
    {
        removeEventListener(EffectEvent.EFFECT_END, windowUnminimizeHandler);
    }

    /**
     *  @private
     */
    private function window_moveHandler(event:NativeWindowBoundsEvent):void
    {
        dispatchEvent(new FlexNativeWindowBoundsEvent(FlexNativeWindowBoundsEvent.WINDOW_MOVE, event.bubbles, event.cancelable,
                    event.beforeBounds, event.afterBounds));
    }

    /**
     *  @private
     */
    private function window_displayStateChangeHandler(
                            event:NativeWindowDisplayStateEvent):void
    {
        // Redispatch event.
        dispatchEvent(event);
        height = systemManager.stage.stageHeight;
        width = systemManager.stage.stageWidth;

        // Restored from a minimized state.
        if (event.beforeDisplayState == NativeWindowDisplayState.MINIMIZED)
        {
            addEventListener(EffectEvent.EFFECT_END, windowUnminimizeHandler);
            dispatchEvent(new Event("windowUnminimize"));
        }
    }

    /**
     *  @private
     */
    private function window_displayStateChangingHandler(
                            event:NativeWindowDisplayStateEvent):void
    {
        //redispatch event for cancellation purposes
        dispatchEvent(event);
        if (event.isDefaultPrevented())
            return;
        if (event.afterDisplayState == NativeWindowDisplayState.MINIMIZED)
        {
            if (getStyle("minimizeEffect"))
            {
                event.preventDefault();
                addEventListener(EffectEvent.EFFECT_END, windowMinimizeHandler);
                dispatchEvent(new Event("windowMinimize"));
            }
        }

    }

    /**
     *  @private
     *  Manages mouse down events on the window border.
     *  
     *  @langversion 3.0
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    protected function mouseDownHandler(event:MouseEvent):void
    {
  
        if (systemManager.stage.nativeWindow.systemChrome != "none")
            return;
        if (event.target == gripperHit)
        {
            startResize(layoutDirection == "rtl" ? NativeWindowResize.BOTTOM_LEFT : NativeWindowResize.BOTTOM_RIGHT);
            event.stopPropagation();
        }
        else
        {
            var dragWidth:int = Number(getStyle("borderThickness")) + 6;
            var cornerSize:int = 12;
            // we short the top a little

            if (event.stageY < Number(getStyle("borderThickness")))
            {
                if (event.stageX < cornerSize)
                    startResize(NativeWindowResize.TOP_LEFT);
                else if (event.stageX > width - cornerSize)
                    startResize(NativeWindowResize.TOP_RIGHT);
                else
                    startResize(NativeWindowResize.TOP);
            }

            else if (event.stageY > (height - dragWidth))
            {
                if (event.stageX < cornerSize)
                     startResize(NativeWindowResize.BOTTOM_LEFT);
                else if (event.stageX > width - cornerSize)
                    startResize(NativeWindowResize.BOTTOM_RIGHT);
                else
                    startResize(NativeWindowResize.BOTTOM);
            }

            else if (event.stageX < dragWidth )
            {
                if (event.stageY < cornerSize)
                    startResize(NativeWindowResize.TOP_LEFT);
                else if (event.stageY > height - cornerSize)
                    startResize(NativeWindowResize.BOTTOM_LEFT);
                else
                    startResize(NativeWindowResize.LEFT);
                event.stopPropagation();
            }

            else if (event.stageX > width - dragWidth)
            {
                if (event.stageY < cornerSize)
                    startResize(NativeWindowResize.TOP_RIGHT);
                else if (event.stageY > height - cornerSize)
                    startResize(NativeWindowResize.BOTTOM_RIGHT);
                else
                    startResize(NativeWindowResize.RIGHT);
            }
        }
    }

    /**
     *  @private
     */
    private function closeButton_clickHandler(event:Event):void
    {
       stage.nativeWindow.close();
    }

    /**
     *  @private
     */
    private function preinitializeHandler(event:Event = null):void
    {
        systemManager.stage.nativeWindow.addEventListener(
            NativeWindowDisplayStateEvent.DISPLAY_STATE_CHANGING,
            window_displayStateChangingHandler);
        systemManager.stage.nativeWindow.addEventListener(
            NativeWindowDisplayStateEvent.DISPLAY_STATE_CHANGE,
            window_displayStateChangeHandler)
        systemManager.stage.nativeWindow.addEventListener(
            "closing", window_closingHandler);
        systemManager.stage.nativeWindow.addEventListener(
            "close", window_closeHandler, false, 0, true);
            
        // For the edge case, e.g. visible is set to true in
        // AIR xml file, we fabricate an activate event, since Flex 
        // comes in late to the show.
        if (systemManager.stage.nativeWindow.active) 
            dispatchEvent(new AIREvent(AIREvent.WINDOW_ACTIVATE));
                        
        systemManager.stage.nativeWindow.addEventListener(
            "activate", nativeWindow_activateHandler, false, 0, true);
        systemManager.stage.nativeWindow.addEventListener(
            "deactivate", nativeWindow_deactivateHandler, false, 0, true);
                        
        systemManager.stage.nativeWindow.addEventListener(
            NativeWindowBoundsEvent.MOVING, window_boundsHandler);

        systemManager.stage.nativeWindow.addEventListener(
            NativeWindowBoundsEvent.MOVE, window_moveHandler);

        systemManager.stage.nativeWindow.addEventListener(
            NativeWindowBoundsEvent.RESIZING, window_boundsHandler);

        systemManager.stage.nativeWindow.addEventListener(
           NativeWindowBoundsEvent.RESIZE, window_resizeHandler);

        systemManager.stage.addEventListener(
            FullScreenEvent.FULL_SCREEN, stage_fullScreenHandler);
    }

    /**
     *  @private
     */
    private function mouseMoveHandler(event:MouseEvent):void
    {
        stage.nativeWindow.x += event.stageX - prevX;
        stage.nativeWindow.y += event.stageY - prevY;
    }

    /**
     *  @private
     */
    private function mouseUpHandler(event:MouseEvent):void
    {
        removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
        removeEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
    }

    /**
     *  @private
     */
    private function window_boundsHandler(event:NativeWindowBoundsEvent):void
    {

        var newBounds:Rectangle = event.afterBounds;
        var r:Rectangle;
        if (event.type == NativeWindowBoundsEvent.MOVING)
        {
            dispatchEvent(event);
            if (event.isDefaultPrevented())
                return;
        }
        else //event is resizing
        {
            dispatchEvent(event);
            if (event.isDefaultPrevented())
                return;
            var cancel:Boolean = false;
           if (newBounds.width < nativeWindow.minSize.x)
            {   
                cancel = true;
                if (newBounds.x != event.beforeBounds.x && !isNaN(oldX))
                    newBounds.x = oldX;
                newBounds.width = nativeWindow.minSize.x;
            }
            else if (newBounds.width > nativeWindow.maxSize.x)
            {
                cancel = true;
                if (newBounds.x != event.beforeBounds.x && !isNaN(oldX))
                    newBounds.x = oldX;
                newBounds.width = nativeWindow.maxSize.x;
            }
            if (newBounds.height < nativeWindow.minSize.y)
            {
                cancel = true;
                if (event.afterBounds.y != event.beforeBounds.y && !isNaN(oldY))
                    newBounds.y = oldY;
                newBounds.height = nativeWindow.minSize.y;
            }
            else if (newBounds.height > nativeWindow.maxSize.y)
            {
                cancel = true;
                if (event.afterBounds.y != event.beforeBounds.y && !isNaN(oldY))
                    newBounds.y = oldY;
                newBounds.height = nativeWindow.maxSize.y;
            }
            if (cancel)
            {
                event.preventDefault();
                stage.nativeWindow.bounds = newBounds;
                windowBoundsChanged = true;
                invalidateProperties();
            }
        }
        oldX = newBounds.x;
        oldY = newBounds.y;
    }

    /**
     *  @private
     */
    private function stage_fullScreenHandler(event:FullScreenEvent):void
    {
        //work around double events
        if (stage.displayState != lastDisplayState)
        {
            lastDisplayState = stage.displayState;
            if (stage.displayState == StageDisplayState.FULL_SCREEN ||
                stage.displayState == StageDisplayState.FULL_SCREEN_INTERACTIVE)
            {
                shouldShowTitleBar = showTitleBar;
                showTitleBar = false;
            }
            else
                showTitleBar = shouldShowTitleBar;
        }
    }       
        
    /**
     *  @private
     */
    private function window_closeEffectEndHandler(event:Event):void
    {
        removeEventListener(EffectEvent.EFFECT_END, window_closeEffectEndHandler);
        if (!nativeWindow.closed)
            stage.nativeWindow.close();
    }

    /**
     *  @private
     */
    private function window_closingHandler(event:Event):void
    {
        var e:Event = new Event("closing", true, true);
        dispatchEvent(e);
        if (e.isDefaultPrevented())
        {
            event.preventDefault();
        }
        else if (getStyle("closeEffect") &&
                 stage.nativeWindow.transparent == true)
        {
            addEventListener(EffectEvent.EFFECT_END, window_closeEffectEndHandler);
            dispatchEvent(new Event("windowClose"));
            event.preventDefault();
        }
    }

    /**
     *  @private
     */
    private function window_closeHandler(event:Event):void
    {
        dispatchEvent(new Event("close"));
    }
        
    /**
     *  @private
     */
    private function window_resizeHandler(event:NativeWindowBoundsEvent):void
    {
        // Only validateNow if we don't already have a window bounds
    // update pending. Otherwise, we'll miss a chance to layout with
        // the modified bounds.  ** We really should revisit why we call
        // validateNow here to begin with **.
        if (!windowBoundsChanged)
        {
            windowBoundsChanged= true;
            invalidateProperties();
            invalidateViewMetricsAndPadding();
            invalidateDisplayList();
            validateNow();
        }
        
        var e:FlexNativeWindowBoundsEvent =
                new FlexNativeWindowBoundsEvent(FlexNativeWindowBoundsEvent.WINDOW_RESIZE, event.bubbles, event.cancelable,
                event.beforeBounds, event.afterBounds);
        dispatchEvent(e);
     }

    /**
     *  @private
     */
    private function nativeApplication_activateHandler(event:Event):void
    {
        dispatchEvent(new AIREvent(AIREvent.APPLICATION_ACTIVATE));
        
        // Only the initial WindowedApplication instance manages background framerate.
        var isPrimaryApplication:Boolean = 
            SystemManagerGlobals.topLevelSystemManagers[0] == systemManager;
        
        // Restore throttled framerate if appropriate when application is activated.
        if (prevActiveFrameRate >= 0 && stage && isPrimaryApplication)
        {
            stage.frameRate = prevActiveFrameRate;  
            prevActiveFrameRate = -1;
        }
    }

    /**
     *  @private
     */
    private function nativeApplication_deactivateHandler(event:Event):void
    {
        dispatchEvent(new AIREvent(AIREvent.APPLICATION_DEACTIVATE));
        
        // Only the initial WindowedApplication instance manages background framerate.
        var isPrimaryApplication:Boolean = 
            SystemManagerGlobals.topLevelSystemManagers[0] == systemManager;
                
        // Throttle framerate if appropriate when application is deactivated.
        // Ensure we've received an updateComplete on the chance our layout
        // manager is using phased instantiation (we don't wish to store a
        // maxed out (1000fps) framerate).
        if ((_backgroundFrameRate >= 0) && (ucCount > 0) && stage && isPrimaryApplication)
        {
            prevActiveFrameRate = stage.frameRate;
            stage.frameRate = _backgroundFrameRate; 
        }
    }

    /**
     *  @private
     */
    private function nativeApplication_invokeHandler(event:InvokeEvent):void
    {
        // Because of the behavior with the nativeApplication invoke event
        // we queue events up until windowComplete
        if (invokesPending)
            initialInvokes.push(event);
        else
            dispatchEvent(event);
    }
    
    /**
     * @private
     */
    private function nativeWindow_activateHandler(event:Event):void
    {
        dispatchEvent(new AIREvent(AIREvent.WINDOW_ACTIVATE));
    }

    /**
     *  @private
     */
    private function nativeWindow_deactivateHandler(event:Event):void
    {
        dispatchEvent(new AIREvent(AIREvent.WINDOW_DEACTIVATE));
    }
    
    /**
     *  This is a temporary event handler which dispatches a initialLayoutComplete event after
     *  two updateCompletes. This event will only be dispatched after either setting the bounds or
     *  maximizing the window at startup.
     *  
     *  @langversion 3.0
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    private function updateComplete_handler(event:FlexEvent):void
    {
        if (ucCount == 1)
        {
            dispatchEvent(new Event("initialLayoutComplete"));
            removeEventListener(FlexEvent.UPDATE_COMPLETE, updateComplete_handler);
        }
        else
        {
            ucCount++;
        }
    }

    /**
     *  @private
     *  Returns a Function handler that resizes the view source HTML component with the stage.
     */
    private function viewSourceResizeHandler(html:HTML):Function
    {
        return function (e:FlexNativeWindowBoundsEvent):void
        {
            const win:DisplayObject = e.target;
            html.width  = win.width;
            html.height = win.height;
        };
    }

    /**
     *  @private
     *  Returns a Function handler that closes the View Source window when the parent closes.
     */
    private function viewSourceCloseHandler(win:Window):Function
    {
        return function ():void { win.close(); };
    }
}

}
