////////////////////////////////////////////////////////////////////////////////
//
// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////
package mx.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: "left"
,
* "right"
, "auto"
.
*
*
A value of "left"
means the buttons are aligned
* at the left of the title bar.
* A value of "right"
means the buttons are aligned
* at the right of the title bar.
* A value of "auto"
means the buttons are aligned
* at the left of the title bar on Mac OS X and on the
* right on Windows.
"left"
,
* "center"
, "auto"
*
* A value of "left"
means the title is aligned
* at the left of the title bar.
* A value of "center"
means the title is aligned
* at the center of the title bar.
* A value of "auto"
means the title is aligned
* at the left on Windows and at the center on Mac OS X.
undefined
, 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.
*
* The WindowedApplication serves two roles. It is a replacement for the <mx:Application> * 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.
* *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.
* *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).
* * @mxml * *The <mx:WindowedApplication>
tag inherits all of the tag
* attributes of its superclass and adds the following tag attributes:
* <mx:WindowedApplication * Properties * alwaysInFront="false" * autoExit="true" * backgroundFrameRate="-1" * dockIconMenu="null" * maxHeight="2880 less the height of the system chrome" * maxWidth="2880 less the width of the system chrome" * menu="null" * 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="null" * title="" * titleBarFactory="mx.core.ClassFactory" * titleIcon="null" * useNativeDragManager="true" * * Styles * buttonAlignment="auto" * buttonPadding="2" * closeButtonSkin="mx.skins.halo.windowCloseButtonSkin" * gripperPadding="3" * gripperStyleName="gripperStyle" * headerHeight="undefined" * 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="undefined" * titleAlignment="auto" * titleBarBackgroundSkin="mx.skins.halo.ApplicationTitleBarBackgroundSkin" * titleBarButtonPadding="5" * titleBarColors="[ 0x000000, 0x000000 ]" * titleTextStyleName="undefined" * * Effects * closeEffect="No default" * minimizeEffect="No default" * unminimizeEffect="No default" * * Events * applicationActivate="No default" * applicationDeactivate="No default" * closing="No default" * displayStateChange="No default" * displayStateChanging="No default" * invoke="No default" * moving="No default" * networkChange="No default" * resizing="No default" * windowComplete="No default" * windowMove="No default" * windowResize="No default" * /> ** * * @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
true
, the gripper is visible.
*
* On Mac OS X a window with systemChrome
* set to "standard"
* always has an operating system gripper, so this property is ignored
* in that case.
true
, 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 true
, 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.
*
* If you write a custom status bar class, it should expose
* a public property named status
.
If you write a custom title bar class, it should expose
* public properties named titleIcon
* and title
.
true
, the DragManager should use the NativeDragManagerImpl implementation class.
* If false
, then the DragManagerImpl class will be used.
*
* 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.
* *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.
* *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.
* *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.
* * @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'sorderInBackOf()
method.
*
* @param window The IWindow (Window or WindowedAplication)
* to order this window behind.
*
* @return true
if the window was succesfully sent behind;
* false
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 orderInFrontOf()
method.
*
* @param window The IWindow (Window or WindowedAplication)
* to order this window in front of.
*
* @return true
if the window was succesfully sent in front;
* false
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 true
if the window was succesfully sent to the back;
* false
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 true
if the window was succesfully sent to the front;
* false
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(); };
}
}
}