You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by ah...@apache.org on 2016/06/03 17:55:23 UTC
[4/6] git commit: [flex-asjs] [refs/heads/spark] - clean compile of
MX for swf
http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/4f3802ef/frameworks/projects/MX/src/main/flex/mx/managers/FocusManager.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/MX/src/main/flex/mx/managers/FocusManager.as b/frameworks/projects/MX/src/main/flex/mx/managers/FocusManager.as
new file mode 100644
index 0000000..105c979
--- /dev/null
+++ b/frameworks/projects/MX/src/main/flex/mx/managers/FocusManager.as
@@ -0,0 +1,2359 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package mx.managers
+{
+
+COMPILE::AS3
+{
+import flash.display.DisplayObject;
+import flash.display.DisplayObjectContainer;
+import flash.display.InteractiveObject;
+import flash.display.Stage;
+import flash.events.Event;
+import flash.events.EventDispatcher;
+import flash.events.FocusEvent;
+import flash.events.KeyboardEvent;
+import flash.events.MouseEvent;
+import flash.system.Capabilities;
+import flash.system.IME;
+import flash.text.TextField;
+import flash.ui.Keyboard;
+}
+
+COMPILE::LATER
+{
+import mx.core.FlexSprite;
+import mx.core.ISWFLoader;
+import mx.core.IVisualElement;
+}
+import mx.core.IButton;
+import mx.core.IChildList;
+import mx.core.IIMESupport;
+import mx.core.IRawChildrenContainer;
+import mx.core.IToggleButton;
+import mx.core.IUIComponent;
+import mx.core.mx_internal;
+import mx.events.FlexEvent;
+import mx.utils.Platform;
+
+import flex.display.Sprite;
+
+import org.apache.flex.core.IUIBase;
+
+use namespace mx_internal;
+
+/**
+ * The FocusManager class manages the focus on components in response to mouse
+ * activity or keyboard activity (Tab key). There can be several FocusManager
+ * instances in an application. Each FocusManager instance
+ * is responsible for a set of components that comprise a "tab loop". If you
+ * hit Tab enough times, focus traverses through a set of components and
+ * eventually get back to the first component that had focus. That is a "tab loop"
+ * and a FocusManager instance manages that loop. If there are popup windows
+ * with their own set of components in a "tab loop" those popup windows will have
+ * their own FocusManager instances. The main application always has a
+ * FocusManager instance.
+ *
+ * <p>The FocusManager manages focus from the "component level".
+ * In Flex, a UITextField in a component is the only way to allow keyboard entry
+ * of text. To the Flash Player or AIR, that UITextField has focus. However, from the
+ * FocusManager's perspective the component that parents the UITextField has focus.
+ * Thus there is a distinction between component-level focus and player-level focus.
+ * Application developers generally only have to deal with component-level focus while
+ * component developers must understand player-level focus.</p>
+ *
+ * <p>All components that can be managed by the FocusManager must implement
+ * mx.managers.IFocusManagerComponent, whereas objects managed by player-level focus do not.</p>
+ *
+ * <p>The FocusManager also managers the concept of a defaultButton, which is
+ * the Button on a form that dispatches a click event when the Enter key is pressed
+ * depending on where focus is at that time.</p>
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+public class FocusManager extends EventDispatcher implements IFocusManager
+{
+ include "../core/Version.as";
+
+ //--------------------------------------------------------------------------
+ //
+ // Class constants
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ *
+ * Default value of parameter, ignore.
+ */
+ private static const FROM_INDEX_UNSPECIFIED:int = -2;
+
+ //--------------------------------------------------------------------------
+ //
+ // Class variables
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ *
+ * Place to hook in additional classes
+ */
+ public static var mixins:Array;
+
+ // flag to turn on/off some ie specific behavior
+ mx_internal static var ieshifttab:Boolean = true;
+
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * <p>A FocusManager manages the focus within the children of an IFocusManagerContainer.
+ * It installs itself in the IFocusManagerContainer during execution
+ * of the constructor.</p>
+ *
+ * @param container An IFocusManagerContainer that hosts the FocusManager.
+ *
+ * @param popup If <code>true</code>, indicates that the container
+ * is a popup component and not the main application.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ public function FocusManager(container:IFocusManagerContainer, popup:Boolean = false)
+ {
+ super();
+
+ this.popup = popup;
+
+ IMEEnabled = true;
+ // Only <= IE8 supported focus cycling out of the SWF
+ browserMode = Capabilities.playerType == "ActiveX" && !popup;
+ desktopMode = Platform.isAir && !popup;
+ // Flash main windows come up activated, AIR main windows don't
+ windowActivated = !desktopMode;
+
+ container.focusManager = this; // this property name is reserved in the parent
+
+ // trace("FocusManager constructor " + container + ".focusManager");
+
+ _form = container;
+
+ focusableObjects = [];
+
+ focusPane = new Sprite();
+ focusPane.name = "focusPane";
+
+ addFocusables(DisplayObject(container));
+
+ // Listen to the stage so we know when the root application is loaded.
+ container.addEventListener(Event.ADDED, addedHandler);
+ container.addEventListener(Event.REMOVED, removedHandler);
+ container.addEventListener(FlexEvent.SHOW, showHandler);
+ container.addEventListener(FlexEvent.HIDE, hideHandler);
+ container.addEventListener(FlexEvent.HIDE, childHideHandler, true);
+ container.addEventListener("_navigationChange_",viewHideHandler, true);
+
+ //special case application and window
+ if (container.systemManager is SystemManager)
+ {
+ // special case application. It shouldn't need to be made
+ // active and because we defer appCreationComplete, this
+ // would steal focus back from any popups created during
+ // instantiation
+ if (container != SystemManager(container.systemManager).application)
+ container.addEventListener(FlexEvent.CREATION_COMPLETE,
+ creationCompleteHandler);
+ }
+
+ if (mixins)
+ {
+ var n:int = mixins.length;
+ for (var i:int = 0; i < n; i++)
+ {
+ new mixins[i](this);
+ }
+ }
+
+ // Make sure the SystemManager is running so it can tell us about
+ // mouse clicks and stage size changes.
+ try
+ {
+ var awm:IActiveWindowManager =
+ IActiveWindowManager(container.systemManager.getImplementation("mx.managers::IActiveWindowManager"));
+ if (awm)
+ awm.addFocusManager(container); // build a message that does the equal
+
+ if (hasEventListener("initialize"))
+ dispatchEvent(new Event("initialize"));
+
+ }
+ catch (e:Error)
+ {
+ // ignore null pointer errors caused by container using a
+ // systemManager from another sandbox.
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Variables
+ //
+ //--------------------------------------------------------------------------
+
+ private var LARGE_TAB_INDEX:int = 99999;
+
+ mx_internal var calculateCandidates:Boolean = true;
+
+ /**
+ * @private
+ *
+ * True if this focus manager is a popup, false if it is a main application.
+ *
+ */
+ mx_internal var popup:Boolean;
+
+ /**
+ * @private
+ *
+ * True if this focus manager will try to enable/disable the IME based on
+ * whether the focused control uses IME. Leaving this as a backdoor just in case.
+ *
+ */
+ mx_internal var IMEEnabled:Boolean;
+
+ /**
+ * @private
+ * We track whether we've been last activated or saw a TAB
+ * This is used in browser tab management
+ */
+ mx_internal var lastAction:String;
+
+ /**
+ * @private
+ * Tab management changes based on whether were in a browser or not
+ * This value is also affected by whether you are a modal dialog or not
+ */
+ public var browserMode:Boolean;
+
+ /**
+ * @private
+ * Activation changes depending on whether we're running in AIR or not
+ */
+ public var desktopMode:Boolean;
+
+ /**
+ * @private
+ * Tab management changes based on whether were in a browser or not
+ * If non-null, this is the object that will
+ * lose focus to the browser
+ */
+ private var browserFocusComponent:InteractiveObject;
+
+ /**
+ * @private
+ * Total set of all objects that can receive focus
+ * but might be disabled or invisible.
+ */
+ mx_internal var focusableObjects:Array;
+
+ /**
+ * @private
+ * Filtered set of objects that can receive focus right now.
+ */
+ private var focusableCandidates:Array;
+
+ /**
+ * @private
+ */
+ private var activated:Boolean;
+ /**
+ * @private
+ */
+ private var windowActivated:Boolean;
+
+ /**
+ * @private
+ *
+ * true if focus was changed to one of focusable objects. False if focus passed to
+ * the browser.
+ */
+ mx_internal var focusChanged:Boolean;
+
+ /**
+ * @private
+ *
+ * if non-null, the location to move focus from instead of the object
+ * that has focus in the stage.
+ */
+ mx_internal var fauxFocus:DisplayObject;
+
+
+ //--------------------------------------------------------------------------
+ //
+ // Properties
+ //
+ //--------------------------------------------------------------------------
+
+ //----------------------------------
+ // showFocusIndicator
+ //----------------------------------
+
+ /**
+ * @private
+ * Storage for the showFocusIndicator property.
+ */
+ mx_internal var _showFocusIndicator:Boolean = false;
+
+ /**
+ * @inheritDoc
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ public function get showFocusIndicator():Boolean
+ {
+ return _showFocusIndicator;
+ }
+
+ /**
+ * @private
+ */
+ public function set showFocusIndicator(value:Boolean):void
+ {
+ var changed:Boolean = _showFocusIndicator != value;
+ // trace("FM " + this + " showFocusIndicator = " + value);
+ _showFocusIndicator = value;
+
+ if (hasEventListener("showFocusIndicator"))
+ dispatchEvent(new Event("showFocusIndicator"));
+ }
+
+ //----------------------------------
+ // defaultButton
+ //----------------------------------
+
+ /**
+ * @private
+ * The current default button.
+ */
+ private var defButton:IButton;
+
+ /**
+ * @private
+ */
+ private var _defaultButton:IButton;
+
+ /**
+ * @inheritDoc
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ public function get defaultButton():IButton
+ {
+ return _defaultButton;
+ }
+
+ /**
+ * @private
+ * We don't type the value as Button for dependency reasons
+ */
+ public function set defaultButton(value:IButton):void
+ {
+ var button:IButton = value ? IButton(value) : null;
+
+ if (button != _defaultButton)
+ {
+ if (_defaultButton)
+ _defaultButton.emphasized = false;
+
+ if (defButton)
+ defButton.emphasized = false;
+
+ _defaultButton = button;
+
+ if (defButton != _lastFocus || _lastFocus == _defaultButton)
+ {
+ defButton = button;
+
+ if (button)
+ button.emphasized = true;
+ }
+ }
+ }
+
+ //----------------------------------
+ // defaultButtonEnabled
+ //----------------------------------
+
+ /**
+ * @private
+ * Storage for the defaultButtonEnabled property.
+ */
+ private var _defaultButtonEnabled:Boolean = true;
+
+ /**
+ * @inheritDoc
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ public function get defaultButtonEnabled():Boolean
+ {
+ return _defaultButtonEnabled;
+ }
+
+ /**
+ * @private
+ */
+ public function set defaultButtonEnabled(value:Boolean):void
+ {
+ _defaultButtonEnabled = value;
+
+ // Synchronize with the new value. We ensure that our
+ // default button is de-emphasized if defaultButtonEnabled
+ // is false.
+ if (defButton)
+ defButton.emphasized = value;
+ }
+
+ //----------------------------------
+ // focusPane
+ //----------------------------------
+
+ /**
+ * @private
+ * Storage for the focusPane property.
+ */
+ private var _focusPane:Sprite;
+
+ /**
+ * @inheritDoc
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ public function get focusPane():Sprite
+ {
+ return _focusPane;
+ }
+
+ /**
+ * @private
+ */
+ public function set focusPane(value:Sprite):void
+ {
+ _focusPane = value;
+ }
+
+ //----------------------------------
+ // form
+ //----------------------------------
+
+ /**
+ * @private
+ * Storage for the form property.
+ */
+ private var _form:IFocusManagerContainer;
+
+ /**
+ * @private
+ * The form is the property where we store the IFocusManagerContainer
+ * that hosts this FocusManager.
+ */
+ mx_internal function get form():IFocusManagerContainer
+ {
+ return _form;
+ }
+
+ /**
+ * @private
+ */
+ mx_internal function set form (value:IFocusManagerContainer):void
+ {
+ _form = value;
+ }
+
+
+ //----------------------------------
+ // _lastFocus
+ //----------------------------------
+
+ /**
+ * @private
+ * the object that last had focus
+ */
+ private var _lastFocus:IFocusManagerComponent;
+
+
+ /**
+ * @private
+ */
+ mx_internal function get lastFocus():IFocusManagerComponent
+ {
+ return _lastFocus;
+ }
+
+ /**
+ * @private
+ */
+ mx_internal function set lastFocus(value:IFocusManagerComponent):void
+ {
+ _lastFocus = value;
+ }
+
+ //----------------------------------
+ // nextTabIndex
+ //----------------------------------
+
+ /**
+ * @inheritDoc
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ public function get nextTabIndex():int
+ {
+ return getMaxTabIndex() + 1;
+ }
+
+ /**
+ * Gets the highest tab index currently used in this Focus Manager's form or subform.
+ *
+ * @return Highest tab index currently used.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ private function getMaxTabIndex():int
+ {
+ var z:Number = 0;
+
+ var n:int = focusableObjects.length;
+ for (var i:int = 0; i < n; i++)
+ {
+ var t:Number = focusableObjects[i].tabIndex;
+ if (!isNaN(t))
+ z = Math.max(z, t);
+ }
+
+ return z;
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Methods
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @inheritDoc
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ public function getFocus():IFocusManagerComponent
+ {
+ var stage:Stage = form.systemManager.stage;
+
+ if (!stage)
+ return null;
+
+ var o:InteractiveObject = stage.focus;
+ var i:IUIBase;
+ while (o != null)
+ {
+ if (o is IUIBase)
+ {
+ i = o as IUIBase;
+ break;
+ }
+ o = o.parent;
+ }
+
+ // If a Stage* object (such as StageText or StageWebView) has focus,
+ // stage.focus will be set to null. Much of the focus framework is not
+ // set up to handle this. So, if stage.focus is null, we return the last
+ // IFocusManagerComponent that had focus. In ADL, focus works slightly
+ // different than it does on device when using StageText. In ADL, when
+ // the focus is a StageText component, a TextField whose parent is the
+ // stage is assigned focus.
+ if ((!o && _lastFocus) || (o is TextField && o.parent == stage))
+ return _lastFocus;
+
+ return findFocusManagerComponent(i);
+ }
+
+ /**
+ * @inheritDoc
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ public function setFocus(o:IFocusManagerComponent):void
+ {
+ // trace("FM " + this + " setting focus to " + o);
+
+ o.setFocus();
+
+ if (hasEventListener("setFocus"))
+ dispatchEvent(new Event("setFocus"));
+ // trace("FM set focus");
+ }
+
+ /**
+ * @private
+ */
+ private function focusInHandler(event:FocusEvent):void
+ {
+ var target:InteractiveObject = InteractiveObject(event.target);
+ // trace("FocusManager focusInHandler in = " + this._form.systemManager.loaderInfo.url);
+ // trace("FM " + this + " focusInHandler " + target);
+
+ // dispatch cancelable FocusIn to see if Marshal Plan mixin wants it
+ if (hasEventListener(FocusEvent.FOCUS_IN))
+ if (!dispatchEvent(new FocusEvent(FocusEvent.FOCUS_IN, false, true, target)))
+ return;
+
+ if (isParent(DisplayObjectContainer(form), target))
+ {
+ if (_defaultButton)
+ {
+ if (target is IButton && target != _defaultButton
+ && !(target is IToggleButton))
+ _defaultButton.emphasized = false;
+ else if (_defaultButtonEnabled)
+ _defaultButton.emphasized = true;
+ }
+
+ var o:InteractiveObject = target;
+ var i:IUIBase;
+ while (o != null)
+ {
+ if (o is IUIBase)
+ {
+ i = o as IUIBase;
+ break;
+ }
+ o = o.parent;
+ }
+ // trace("FM " + this + " setting last focus " + target);
+ _lastFocus = findFocusManagerComponent(i);
+
+ if (Capabilities.hasIME)
+ {
+ var usesIME:Boolean;
+ if (_lastFocus is IIMESupport)
+ {
+ var imeFocus:IIMESupport = IIMESupport(_lastFocus);
+ if (imeFocus.enableIME)
+ usesIME = true;
+ }
+ if (IMEEnabled)
+ IME.enabled = usesIME;
+ }
+
+ // handle default button here
+ // we can't check for Button because of cross-versioning so
+ // for now we just check for an emphasized property
+ if (_lastFocus is IButton && !(_lastFocus is IToggleButton))
+ {
+ defButton = _lastFocus as IButton;
+ }
+ else
+ {
+ // restore the default button to be the original one
+ if (defButton && defButton != _defaultButton)
+ defButton = _defaultButton;
+ }
+ }
+ }
+
+ /**
+ * @private Useful for debugging
+ */
+ private function focusOutHandler(event:FocusEvent):void
+ {
+ var target:InteractiveObject = InteractiveObject(event.target);
+ // trace("FocusManager focusOutHandler in = " + this._form.systemManager.loaderInfo.url);
+ // trace("FM " + this + " focusOutHandler " + target);
+ }
+
+ /**
+ * @private
+ * restore focus to whoever had it last
+ */
+ private function activateHandler(event:Event):void
+ {
+// var target:InteractiveObject = InteractiveObject(event.target);
+ // trace("FM " + this + " activateHandler ", _lastFocus);
+
+ // if we were the active FM when we were deactivated
+ // and we're not running in AIR, then dispatch the event now
+ // otherwise wait for the AIR events to fire
+ if (activated && !desktopMode)
+ {
+ dispatchEvent(new FlexEvent(FlexEvent.FLEX_WINDOW_ACTIVATE));
+ // restore focus if this focus manager had last focus
+ if (_lastFocus && (!browserMode || ieshifttab))
+ _lastFocus.setFocus();
+ lastAction = "ACTIVATE";
+ }
+ }
+
+ /**
+ * @private
+ * Dispatch event if we're not running in AIR. AIR will
+ * dispatch windowDeactivate that we respond to instead
+ */
+ private function deactivateHandler(event:Event):void
+ {
+ // var target:InteractiveObject = InteractiveObject(event.target);
+ // trace("FM " + this + " deactivateHandler ", _lastFocus);
+
+ // if we are the active FM when we were deactivated
+ // and we're not running in AIR, then dispatch the event now
+ // otherwise wait for the AIR events to fire
+ if (activated && !desktopMode)
+ {
+ dispatchEvent(new FlexEvent(FlexEvent.FLEX_WINDOW_DEACTIVATE));
+ }
+ }
+
+ /**
+ * @private
+ * restore focus to whoever had it last
+ */
+ private function activateWindowHandler(event:Event):void
+ {
+// var target:InteractiveObject = InteractiveObject(event.target);
+ // trace("FM " + this + " activateWindowHandler ", _lastFocus);
+
+ windowActivated = true;
+
+ if (activated)
+ {
+ dispatchEvent(new FlexEvent(FlexEvent.FLEX_WINDOW_ACTIVATE));
+ // restore focus if this focus manager had last focus
+ if (_lastFocus && !browserMode)
+ _lastFocus.setFocus();
+ lastAction = "ACTIVATE";
+ }
+ }
+
+ /**
+ * @private
+ * If we're responsible for the focused control, remove focus from it
+ * so it gets the same events as it would if the whole app lost focus
+ */
+ private function deactivateWindowHandler(event:Event):void
+ {
+ // var target:InteractiveObject = InteractiveObject(event.target);
+ // trace("FM " + this + " deactivateWindowHandler ", _lastFocus);
+
+ windowActivated = false;
+
+ if (activated)
+ {
+ dispatchEvent(new FlexEvent(FlexEvent.FLEX_WINDOW_DEACTIVATE));
+ if (form.systemManager.stage)
+ form.systemManager.stage.focus = null;
+ }
+ }
+
+ /**
+ * @inheritDoc
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ public function showFocus():void
+ {
+ if (!showFocusIndicator)
+ {
+ showFocusIndicator = true;
+ if (_lastFocus)
+ _lastFocus.drawFocus(true);
+ }
+ }
+
+ /**
+ * @inheritDoc
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ public function hideFocus():void
+ {
+ // trace("FOcusManger " + this + " Hide Focus");
+ if (showFocusIndicator)
+ {
+ showFocusIndicator = false;
+ if (_lastFocus)
+ _lastFocus.drawFocus(false);
+ }
+ // trace("END FOcusManger Hide Focus");
+ }
+
+ /**
+ * The SystemManager activates and deactivates a FocusManager
+ * if more than one IFocusManagerContainer is visible at the same time.
+ * If the mouse is clicked in an IFocusManagerContainer with a deactivated
+ * FocusManager, the SystemManager will call
+ * the <code>activate()</code> method on that FocusManager.
+ * The FocusManager that was activated will have its <code>deactivate()</code> method
+ * called prior to the activation of another FocusManager.
+ *
+ * <p>The FocusManager adds event handlers that allow it to monitor
+ * focus related keyboard and mouse activity.</p>
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ public function activate():void
+ {
+ // we can get a double activation if we're popping up and becoming visible
+ // like the second time a menu appears
+ if (activated)
+ {
+ // trace("FocusManager is already active " + this);
+ return;
+ }
+
+ // trace("FocusManager activating = " + this._form.systemManager.loaderInfo.url);
+ // trace("FocusManager activating " + this);
+
+ // listen for focus changes, use weak references for the stage
+ // form.systemManager can be null if the form is created in a sandbox and
+ // added as a child to the root system manager.
+ var sm:ISystemManager = form.systemManager;
+ if (sm)
+ {
+ if (sm.isTopLevelRoot())
+ {
+ sm.stage.addEventListener(FocusEvent.MOUSE_FOCUS_CHANGE, mouseFocusChangeHandler, false, 0, true);
+ sm.stage.addEventListener(FocusEvent.KEY_FOCUS_CHANGE, keyFocusChangeHandler, false, 0, true);
+ sm.stage.addEventListener(Event.ACTIVATE, activateHandler, false, 0, true);
+ sm.stage.addEventListener(Event.DEACTIVATE, deactivateHandler, false, 0, true);
+ }
+ else
+ {
+ sm.addEventListener(FocusEvent.MOUSE_FOCUS_CHANGE, mouseFocusChangeHandler, false, 0, true);
+ sm.addEventListener(FocusEvent.KEY_FOCUS_CHANGE, keyFocusChangeHandler, false, 0, true);
+ sm.addEventListener(Event.ACTIVATE, activateHandler, false, 0, true);
+ sm.addEventListener(Event.DEACTIVATE, deactivateHandler, false, 0, true);
+ }
+ }
+
+ form.addEventListener(FocusEvent.FOCUS_IN, focusInHandler, true);
+ form.addEventListener(FocusEvent.FOCUS_OUT, focusOutHandler, true);
+ form.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
+ form.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownCaptureHandler, true);
+ form.addEventListener(KeyboardEvent.KEY_DOWN, defaultButtonKeyHandler);
+ form.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler, true);
+ if (sm)
+ {
+ // AIR Window events, but don't want to link in AIREvent
+ // use capture phase because these get sent by the main Window
+ // and we might be managing a popup in that window
+ sm.addEventListener("windowActivate", activateWindowHandler, true, 0, true);
+ sm.addEventListener("windowDeactivate", deactivateWindowHandler, true, 0, true);
+ }
+
+ activated = true;
+ dispatchEvent(new FlexEvent(FlexEvent.FLEX_WINDOW_ACTIVATE));
+
+ // Restore focus to the last control that had it if there was one.
+ if (_lastFocus)
+ setFocus(_lastFocus);
+
+ if (hasEventListener("activateFM"))
+ dispatchEvent(new Event("activateFM"));
+
+ }
+
+ /**
+ * The SystemManager activates and deactivates a FocusManager
+ * if more than one IFocusManagerContainer is visible at the same time.
+ * If the mouse is clicked in an IFocusManagerContainer with a deactivated
+ * FocusManager, the SystemManager will call
+ * the <code>activate()</code> method on that FocusManager.
+ * The FocusManager that was activated will have its <code>deactivate()</code> method
+ * called prior to the activation of another FocusManager.
+ *
+ * <p>The FocusManager removes event handlers that allow it to monitor
+ * focus related keyboard and mouse activity.</p>
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ public function deactivate():void
+ {
+ // trace("FocusManager deactivating " + this);
+ // trace("FocusManager deactivating = " + this._form.systemManager.loaderInfo.url);
+
+ // listen for focus changes
+ var sm:ISystemManager = form.systemManager;
+ if (sm)
+ {
+ if (sm.isTopLevelRoot())
+ {
+ sm.stage.removeEventListener(FocusEvent.MOUSE_FOCUS_CHANGE, mouseFocusChangeHandler);
+ sm.stage.removeEventListener(FocusEvent.KEY_FOCUS_CHANGE, keyFocusChangeHandler);
+ sm.stage.removeEventListener(Event.ACTIVATE, activateHandler);
+ sm.stage.removeEventListener(Event.DEACTIVATE, deactivateHandler);
+ }
+ else
+ {
+ sm.removeEventListener(FocusEvent.MOUSE_FOCUS_CHANGE, mouseFocusChangeHandler);
+ sm.removeEventListener(FocusEvent.KEY_FOCUS_CHANGE, keyFocusChangeHandler);
+ sm.removeEventListener(Event.ACTIVATE, activateHandler);
+ sm.removeEventListener(Event.DEACTIVATE, deactivateHandler);
+ }
+ }
+
+ form.removeEventListener(FocusEvent.FOCUS_IN, focusInHandler, true);
+ form.removeEventListener(FocusEvent.FOCUS_OUT, focusOutHandler, true);
+ form.removeEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
+ form.removeEventListener(MouseEvent.MOUSE_DOWN, mouseDownCaptureHandler, true);
+ form.removeEventListener(KeyboardEvent.KEY_DOWN, defaultButtonKeyHandler);
+ // stop listening for default button in Capture phase
+ form.removeEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler, true);
+
+ activated = false;
+ dispatchEvent(new FlexEvent(FlexEvent.FLEX_WINDOW_DEACTIVATE));
+
+ if (hasEventListener("deactivateFM"))
+ dispatchEvent(new Event("deactivateFM"));
+ }
+
+ /**
+ * @inheritDoc
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ public function findFocusManagerComponent(
+ o:IUIBase):IFocusManagerComponent
+ {
+ return findFocusManagerComponent2(o as InteractiveObject) as IFocusManagerComponent;
+ }
+
+
+ /**
+ * @private
+ *
+ * This version of the method differs from the old one to support SWFLoader
+ * being in the focusableObjects list but not being a component that
+ * gets focus. SWFLoader is in the list of focusable objects so
+ * focus may be passed over a bridge to the components on the other
+ * side of the bridge.
+ */
+ private function findFocusManagerComponent2(
+ o:InteractiveObject):DisplayObject
+
+ {
+ try
+ {
+ while (o)
+ {
+ COMPILE::LATER
+ {
+ if ((o is IFocusManagerComponent && IFocusManagerComponent(o).focusEnabled) ||
+ o is ISWFLoader)
+ return o;
+ }
+ if (o is IFocusManagerComponent && IFocusManagerComponent(o).focusEnabled)
+ return o as DisplayObject;
+
+ o = o.parent;
+ }
+ }
+ catch (error:SecurityError)
+ {
+ // can happen in a loaded child swf
+ // trace("findFocusManagerComponent: handling security error");
+ }
+
+ // tab was set somewhere else
+ return null;
+ }
+
+ /**
+ * @private
+ * Returns true if p is a parent of o.
+ */
+ private function isParent(p:DisplayObjectContainer, o:DisplayObject):Boolean
+ {
+ if (p == o)
+ return false;
+
+ if (p is IRawChildrenContainer)
+ return IRawChildrenContainer(p).rawChildren.contains(o);
+
+ return p.contains(o);
+ }
+
+ private function isEnabledAndVisible(o:DisplayObject):Boolean
+ {
+ var formParent:DisplayObjectContainer = DisplayObjectContainer(form);
+
+ while (o != formParent)
+ {
+ if (o is IUIComponent)
+ if (!IUIComponent(o).enabled)
+ return false;
+
+ COMPILE::LATER
+ {
+ if (o is IVisualElement)
+ if (IVisualElement(o).designLayer && !IVisualElement(o).designLayer.effectiveVisibility)
+ return false;
+ }
+
+ if (!o.visible)
+ return false;
+ o = o.parent;
+
+ // if no parent, then not on display list
+ if (!o)
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * @private
+ */
+ private function sortByTabIndex(a:InteractiveObject, b:InteractiveObject):int
+ {
+ var aa:int = a.tabIndex;
+ var bb:int = b.tabIndex;
+
+ if (aa == -1)
+ aa = int.MAX_VALUE;
+ if (bb == -1)
+ bb = int.MAX_VALUE;
+
+ return (aa > bb ? 1 :
+ aa < bb ? -1 : sortByDepth(DisplayObject(a), DisplayObject(b)));
+ }
+
+ /**
+ * @private
+ */
+ private function sortFocusableObjectsTabIndex():void
+ {
+ // trace("FocusableObjectsTabIndex");
+
+ focusableCandidates = [];
+
+ var n:int = focusableObjects.length;
+ for (var i:int = 0; i < n; i++)
+ {
+ var c:IFocusManagerComponent = focusableObjects[i] as IFocusManagerComponent;
+ COMPILE::LATER
+ {
+ if ((c && c.tabIndex && !isNaN(Number(c.tabIndex))) ||
+ focusableObjects[i] is ISWFLoader)
+ {
+ // if we get here, it is a candidate
+ focusableCandidates.push(focusableObjects[i]);
+ }
+ }
+ if (c && c.tabIndex && !isNaN(Number(c.tabIndex)))
+ {
+ // if we get here, it is a candidate
+ focusableCandidates.push(focusableObjects[i]);
+ }
+ }
+
+ focusableCandidates.sort(sortByTabIndex);
+ }
+
+ /**
+ * @private
+ */
+ private function sortByDepth(aa:DisplayObject, bb:DisplayObject):Number
+ {
+ var val1:String = "";
+ var val2:String = "";
+ var index:int;
+ var tmp:String;
+ var tmp2:String;
+ var zeros:String = "0000";
+
+ var a:DisplayObject = DisplayObject(aa);
+ var b:DisplayObject = DisplayObject(bb);
+
+ // TODO (egreenfi): If a component lives inside of a group, we care about not its display object index, but
+ // its index within the group. See SDK-25144
+
+ while (a != DisplayObject(form) && a.parent)
+ {
+ index = getChildIndex(a.parent, a);
+ tmp = index.toString(16);
+ if (tmp.length < 4)
+ {
+ tmp2 = zeros.substring(0, 4 - tmp.length) + tmp;
+ }
+ val1 = tmp2 + val1;
+ a = a.parent;
+ }
+
+ while (b != DisplayObject(form) && b.parent)
+ {
+ index = getChildIndex(b.parent, b);
+ tmp = index.toString(16);
+ if (tmp.length < 4)
+ {
+ tmp2 = zeros.substring(0, 4 - tmp.length) + tmp;
+ }
+ val2 = tmp2 + val2;
+ b = b.parent;
+ }
+
+ return val1 > val2 ? 1 : val1 < val2 ? -1 : 0;
+ }
+
+ private function getChildIndex(parent:DisplayObjectContainer, child:DisplayObject):int
+ {
+ try
+ {
+ return parent.getChildIndex(child);
+ }
+ catch(e:Error)
+ {
+ if (parent is IRawChildrenContainer)
+ return IRawChildrenContainer(parent).rawChildren.getChildIndex(child);
+ throw e;
+ }
+ throw new Error("FocusManager.getChildIndex failed"); // shouldn't ever get here
+ }
+
+ /**
+ * @private
+ * Calculate what focusableObjects are valid tab candidates.
+ */
+ private function sortFocusableObjects():void
+ {
+ // trace("FocusableObjects " + focusableObjects.length.toString());
+ focusableCandidates = [];
+
+ var n:int = focusableObjects.length;
+ for (var i:int = 0; i < n; i++)
+ {
+ var c:InteractiveObject = focusableObjects[i];
+ // trace(" " + c);
+ if (c.tabIndex && !isNaN(Number(c.tabIndex)) && c.tabIndex > 0)
+ {
+ sortFocusableObjectsTabIndex();
+ return;
+ }
+ focusableCandidates.push(c);
+ }
+
+ focusableCandidates.sort(sortByDepth);
+ }
+
+ /**
+ * Call this method to make the system
+ * think the Enter key was pressed and the defaultButton was clicked
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ mx_internal function sendDefaultButtonEvent():void
+ {
+ // trace("FocusManager.sendDefaultButtonEvent " + defButton);
+ defButton.dispatchEvent(new MouseEvent("click"));
+ }
+
+ /**
+ * @private
+ * Do a tree walk and add all children you can find.
+ */
+ mx_internal function addFocusables(o:DisplayObject, skipTopLevel:Boolean = false):void
+ {
+ // trace(">>addFocusables " + o);
+ if ((o is IFocusManagerComponent) && !skipTopLevel)
+ {
+
+ var addToFocusables:Boolean = false;
+ if (o is IFocusManagerComponent)
+ {
+ var focusable:IFocusManagerComponent = IFocusManagerComponent(o);
+ if (focusable.focusEnabled)
+ {
+ if (focusable.tabFocusEnabled && isTabVisible(o))
+ {
+ addToFocusables = true;
+ }
+ }
+ }
+
+ if (addToFocusables)
+ {
+ if (focusableObjects.indexOf(o) == -1)
+ {
+ focusableObjects.push(o);
+ calculateCandidates = true;
+ // trace("FM added " + o);
+ }
+ }
+ o.addEventListener("tabFocusEnabledChange", tabFocusEnabledChangeHandler);
+ o.addEventListener("tabIndexChange", tabIndexChangeHandler);
+
+ }
+
+ if (o is DisplayObjectContainer)
+ {
+ var doc:DisplayObjectContainer = DisplayObjectContainer(o);
+ // Even if they aren't focusable now,
+ // listen in case they become later.
+ var checkChildren:Boolean;
+
+ if (o is IFocusManagerComponent)
+ {
+ o.addEventListener("hasFocusableChildrenChange", hasFocusableChildrenChangeHandler);
+ checkChildren = IFocusManagerComponent(o).hasFocusableChildren;
+ }
+ else
+ {
+ o.addEventListener("tabChildrenChange", tabChildrenChangeHandler);
+ checkChildren = doc.tabChildren;
+ }
+
+ if (checkChildren)
+ {
+ if (o is IRawChildrenContainer)
+ {
+ // trace("using view rawChildren");
+ var rawChildren:IChildList = IRawChildrenContainer(o).rawChildren;
+ // recursively visit and add children of components
+ // we don't do this for containers because we get individual
+ // adds for the individual children
+ var i:int;
+ for (i = 0; i < rawChildren.numChildren; i++)
+ {
+ try
+ {
+ addFocusables(rawChildren.getChildAt(i));
+ }
+ catch(error:SecurityError)
+ {
+ // Ignore this child if we can't access it
+ // trace("addFocusables: ignoring security error getting child from rawChildren: " + error);
+ }
+ }
+
+ }
+ else
+ {
+ // trace("using container's children");
+ // recursively visit and add children of components
+ // we don't do this for containers because we get individual
+ // adds for the individual children
+ for (i = 0; i < doc.numChildren; i++)
+ {
+ try
+ {
+ addFocusables(doc.getChildAt(i));
+ }
+ catch(error:SecurityError)
+ {
+ // Ignore this child if we can't access it
+ // trace("addFocusables: ignoring security error getting child at document." + error);
+ }
+ }
+ }
+ }
+ }
+ // trace("<<addFocusables " + o);
+ }
+
+ /**
+ * @private
+ * is it really tabbable?
+ */
+ private function isTabVisible(o:DisplayObject):Boolean
+ {
+ var s:DisplayObject = DisplayObject(form.systemManager);
+ if (!s) return false;
+
+ var p:DisplayObjectContainer = o.parent;
+ while (p && p != s)
+ {
+ if (!p.tabChildren)
+ return false;
+ if (p is IFocusManagerComponent && !(IFocusManagerComponent(p).hasFocusableChildren))
+ return false;
+ p = p.parent;
+ }
+ return true;
+ }
+
+ private function isValidFocusCandidate(o:DisplayObject, g:String):Boolean
+ {
+ if (o is IFocusManagerComponent)
+ if (!IFocusManagerComponent(o).focusEnabled)
+ return false;
+
+ if (!isEnabledAndVisible(o))
+ return false;
+
+ if (o is IFocusManagerGroup)
+ {
+ // reject if it is in the same tabgroup
+ var tg:IFocusManagerGroup = IFocusManagerGroup(o);
+ if (g == tg.groupName) return false;
+ }
+ return true;
+ }
+
+ private function getIndexOfFocusedObject(o:DisplayObject):int
+ {
+ if (!o)
+ return -1;
+
+ var n:int = focusableCandidates.length;
+ // trace(" focusableCandidates " + n);
+ var i:int = 0;
+ for (i = 0; i < n; i++)
+ {
+ // trace(" comparing " + focusableCandidates[i]);
+ if (focusableCandidates[i] == o)
+ return i;
+ }
+
+ // no match? try again with a slower match for certain
+ // cases like DG editors
+ for (i = 0; i < n; i++)
+ {
+ var iui:IUIComponent = focusableCandidates[i] as IUIComponent;
+ if (iui && iui.owns(o))
+ return i;
+ }
+
+ return -1;
+ }
+
+
+ private function getIndexOfNextObject(i:int, shiftKey:Boolean, bSearchAll:Boolean, groupName:String):int
+ {
+ var n:int = focusableCandidates.length;
+ var start:int = i;
+
+ while (true)
+ {
+ if (shiftKey)
+ i--;
+ else
+ i++;
+ if (bSearchAll)
+ {
+ if (shiftKey && i < 0)
+ break;
+ if (!shiftKey && i == n)
+ break;
+ }
+ else
+ {
+ i = (i + n) % n;
+ // came around and found the original
+ if (start == i)
+ break;
+ // if start is -1, set start to first valid value of i
+ if (start == -1)
+ start = i;
+ }
+ // trace("testing " + focusableCandidates[i]);
+ if (isValidFocusCandidate(focusableCandidates[i], groupName))
+ {
+ // trace(" stopped at " + i);
+ var o:DisplayObject = DisplayObject(findFocusManagerComponent2(focusableCandidates[i]));
+ if (o is IFocusManagerGroup)
+ {
+
+ // when landing on an element that is part of group, try to
+ // advance selection to the selected group element
+ var j:int;
+ var obj:DisplayObject;
+ var tg1:IFocusManagerGroup = IFocusManagerGroup(o);
+ var tg2:IFocusManagerGroup;
+
+ // normalize the "no selected group element" case
+ // to the "first group element selected" case
+ // (respecting the tab direction)
+ var groupElementToFocus:IFocusManagerGroup = null;
+ for (j = 0; j < focusableCandidates.length; j++)
+ {
+ obj = focusableCandidates[j];
+ if (obj is IFocusManagerGroup)
+ {
+ tg2 = IFocusManagerGroup(obj);
+ if (tg2.groupName == tg1.groupName && isEnabledAndVisible(obj) &&
+ tg2["document"] == tg1["document"])
+ {
+ if (tg2.selected)
+ {
+ groupElementToFocus = tg2;
+ break;
+ }
+ if ((!shiftKey && groupElementToFocus == null) || shiftKey)
+ groupElementToFocus = tg2;
+ }
+ }
+ }
+
+ if (tg1 != groupElementToFocus)
+ {
+ var foundAnotherGroup:Boolean = false;
+ // cycle the entire focusable candidates array forward or backward,
+ // wrapping around boundaries, searching for our focus candidate
+ j = i;
+ for (var k:int = 0; k < focusableCandidates.length - 1; k++)
+ {
+
+ if (!shiftKey)
+ {
+ j++;
+ if (j == focusableCandidates.length)
+ j = 0;
+ }
+ else
+ {
+ j--;
+ if (j == -1)
+ j = focusableCandidates.length - 1;
+ }
+
+ obj = focusableCandidates[j];
+ if (isEnabledAndVisible(obj))
+ {
+ if (foundAnotherGroup)
+ {
+ // we're now just trying to find a selected member of this group
+ if (obj is IFocusManagerGroup)
+ {
+ tg2 = IFocusManagerGroup(obj);
+ if (tg2.groupName == tg1.groupName && tg2["document"] == tg1["document"])
+ {
+ if (tg2.selected)
+ {
+ i = j;
+ break;
+ }
+ }
+ }
+ }
+ else if (obj is IFocusManagerGroup)
+ {
+ tg2 = IFocusManagerGroup(obj);
+ if (tg2.groupName == tg1.groupName && tg2["document"] == tg1["document"])
+ {
+ if (tg2 == groupElementToFocus)
+ {
+ // if objects of same group have different tab index
+ // skip you aren't selected.
+ if (InteractiveObject(obj).tabIndex != InteractiveObject(o).tabIndex && !tg1.selected)
+ return getIndexOfNextObject(i, shiftKey, bSearchAll, groupName);
+ i = j;
+ break;
+ }
+ }
+ else
+ {
+ // switch to new group and hunt for selected item
+ tg1 = tg2;
+ i = j;
+ // element is part of another group, stop if selected
+ if (tg2.selected)
+ break;
+ else
+ foundAnotherGroup = true;
+ }
+ }
+ else
+ {
+ // element isn't part of any group, stop
+ i = j;
+ break;
+ }
+ }
+ }
+ }
+ }
+ return i;
+ }
+ }
+ return i;
+ }
+
+ /**
+ * @private
+ */
+ private function setFocusToNextObject(event:FocusEvent):void
+ {
+ focusChanged = false;
+ if (focusableObjects.length == 0)
+ return;
+
+ var focusInfo:FocusInfo = getNextFocusManagerComponent2(event.shiftKey, fauxFocus);
+ // trace("winner = ", focusInfo.displayObject);
+
+ // If we are about to wrap focus around, send focus back to the parent.
+ if (!popup && (focusInfo.wrapped || !focusInfo.displayObject))
+ {
+ if (hasEventListener("focusWrapping"))
+ if (!dispatchEvent(new FocusEvent("focusWrapping", false, true, null, event.shiftKey)))
+ return;
+ }
+
+ if (!focusInfo.displayObject)
+ {
+ event.preventDefault();
+ return;
+ }
+
+ setFocusToComponent(focusInfo.displayObject, event.shiftKey);
+ }
+
+ private function setFocusToComponent(o:Object, shiftKey:Boolean):void
+ {
+ focusChanged = false;
+ if (o)
+ {
+ if (hasEventListener("setFocusToComponent"))
+ if (!dispatchEvent(new FocusEvent("setFocusToComponent", false, true, InteractiveObject(o), shiftKey)))
+ return;
+
+ if (o is IFocusManagerComplexComponent)
+ {
+ IFocusManagerComplexComponent(o).assignFocus(shiftKey ? "bottom" : "top");
+ focusChanged = true;
+ }
+ else if (o is IFocusManagerComponent)
+ {
+ setFocus(IFocusManagerComponent(o));
+ focusChanged = true;
+ }
+
+ }
+
+ }
+
+ /**
+ * @private
+ */
+ mx_internal function setFocusToNextIndex(index:int, shiftKey:Boolean):void
+ {
+ if (focusableObjects.length == 0)
+ return;
+
+ // I think we'll have time to do this here instead of at creation time
+ // this makes and orders the focusableCandidates array
+ if (calculateCandidates)
+ {
+ sortFocusableObjects();
+ calculateCandidates = false;
+ }
+
+ var focusInfo:FocusInfo = getNextFocusManagerComponent2(shiftKey, null, index);
+
+ // If we are about to wrap focus around, send focus back to the parent.
+ if (!popup && focusInfo.wrapped)
+ {
+ if (hasEventListener("setFocusToNextIndex"))
+ if (!dispatchEvent(new FocusEvent("setFocusToNextIndex", false, true, null, shiftKey)))
+ return;
+ }
+
+ setFocusToComponent(focusInfo.displayObject, shiftKey);
+ }
+
+ /**
+ * @inheritDoc
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ public function getNextFocusManagerComponent(
+ backward:Boolean = false):IFocusManagerComponent
+ {
+ const focusInfo:FocusInfo = getNextFocusManagerComponent2(backward, fauxFocus);
+ return focusInfo ? focusInfo.displayObject as IFocusManagerComponent : null;
+ }
+
+ /**
+ * Find the next object to set focus to.
+ *
+ * @param backward true if moving in the backwards in the tab order, false if moving forward.
+ * @param fromObject object to move focus from, if null move from the current focus.
+ * @param formIndex index to move focus from, if specified use fromIndex to find the
+ * object, not fromObject.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ private function getNextFocusManagerComponent2(
+ backward:Boolean = false,
+ fromObject:DisplayObject = null,
+ fromIndex:int = FROM_INDEX_UNSPECIFIED):FocusInfo
+
+ {
+ if (focusableObjects.length == 0)
+ return null;
+
+ // I think we'll have time to do this here instead of at creation time
+ // this makes and orders the focusableCandidates array
+ if (calculateCandidates)
+ {
+ sortFocusableObjects();
+ calculateCandidates = false;
+ }
+
+ // trace("focus was at " + fromObject);
+ // trace("focusableObjects " + focusableObjects.length);
+ var i:int = fromIndex;
+ if (fromIndex == FROM_INDEX_UNSPECIFIED)
+ {
+ // if there is no passed in object, then get the object that has the focus
+ var o:DisplayObject = fromObject;
+ if (!o)
+ o = form.systemManager.stage.focus;
+ else if (o == form.systemManager.stage)
+ o == null;
+
+ o = DisplayObject(findFocusManagerComponent2(InteractiveObject(o)));
+
+ var g:String = "";
+ if (o is IFocusManagerGroup)
+ {
+ var tg:IFocusManagerGroup = IFocusManagerGroup(o);
+ g = tg.groupName;
+ }
+ i = getIndexOfFocusedObject(o);
+ }
+
+ // trace(" starting at " + i);
+ var bSearchAll:Boolean = false;
+ var start:int = i;
+ if (i == -1) // we didn't find it
+ {
+ if (backward)
+ i = focusableCandidates.length;
+ bSearchAll = true;
+ // trace("search all " + i);
+ }
+
+ var j:int = getIndexOfNextObject(i, backward, bSearchAll, g);
+
+ // if we wrapped around, get if we have a parent we should pass
+ // focus to.
+ var wrapped:Boolean = false;
+ if (backward)
+ {
+ if (j >= i)
+ wrapped = true;
+ }
+ else if (j <= i)
+ wrapped = true;
+
+ var focusInfo:FocusInfo = new FocusInfo();
+
+ focusInfo.displayObject = findFocusManagerComponent2(focusableCandidates[j]);
+ focusInfo.wrapped = wrapped;
+
+ return focusInfo;
+ }
+
+
+ /**
+ * @private
+ */
+ private function getTopLevelFocusTarget(o:InteractiveObject):InteractiveObject
+ {
+ while (o != InteractiveObject(form))
+ {
+ if (o is IFocusManagerComponent &&
+ IFocusManagerComponent(o).focusEnabled &&
+ IFocusManagerComponent(o).mouseFocusEnabled &&
+ (o is IUIComponent ? IUIComponent(o).enabled : true))
+ return o;
+
+ if (hasEventListener("getTopLevelFocusTarget"))
+ if (!dispatchEvent(new FocusEvent("getTopLevelFocusTarget", false, true, o.parent)))
+ return null;
+
+ o = o.parent;
+
+ if (o == null)
+ break;
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns a String representation of the component hosting the FocusManager object,
+ * with the String <code>".focusManager"</code> appended to the end of the String.
+ *
+ * @return Returns a String representation of the component hosting the FocusManager object,
+ * with the String <code>".focusManager"</code> appended to the end of the String.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ override public function toString():String
+ {
+ return Object(form).toString() + ".focusManager";
+ }
+
+ /**
+ * @private
+ *
+ * Clear the browser focus component and undo any tab index we may have set.
+ */
+ private function clearBrowserFocusComponent():void
+ {
+ if (browserFocusComponent)
+ {
+ if (browserFocusComponent.tabIndex == LARGE_TAB_INDEX)
+ browserFocusComponent.tabIndex = -1;
+
+ browserFocusComponent = null;
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Event handlers
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ * Listen for children being added
+ * and see if they are focus candidates.
+ */
+ private function addedHandler(event:Event):void
+ {
+ var target:DisplayObject = DisplayObject(event.target);
+
+ // trace("FM: addedHandler: got added for " + target);
+
+ // if it is truly parented, add it, otherwise it will get added when the top of the tree
+ // gets parented.
+ if (target.stage)
+ {
+ // trace("FM: addedHandler: adding focusables");
+ addFocusables(DisplayObject(event.target));
+ }
+ }
+
+ /**
+ * @private
+ * Listen for children being removed.
+ */
+ private function removedHandler(event:Event):void
+ {
+ var i:int;
+ var o:DisplayObject = DisplayObject(event.target);
+ var focusPaneParent:DisplayObject = focusPane ? focusPane.parent : null;
+
+ // Remove the focusPane to allow the focusOwner to be garbage collected.
+ // Avoid recursion by not processing the removal of the focusPane itself.
+ if (focusPaneParent && o != focusPane)
+ {
+ if (o is DisplayObjectContainer &&
+ isParent(DisplayObjectContainer(o), focusPane))
+ {
+ if (focusPaneParent is ISystemManager)
+ ISystemManager(focusPaneParent).focusPane = null;
+ else
+ IUIComponent(focusPaneParent).focusPane = null;
+ }
+ }
+
+ // trace("FM got added for " + event.target);
+
+ if (o is IFocusManagerComponent)
+ {
+ for (i = 0; i < focusableObjects.length; i++)
+ {
+ if (o == focusableObjects[i])
+ {
+ if (o == _lastFocus)
+ {
+ _lastFocus.drawFocus(false);
+ _lastFocus = null;
+ }
+ // trace("FM removed " + o);
+ focusableObjects.splice(i, 1);
+ focusableCandidates = [];
+ calculateCandidates = true;
+ break;
+ }
+ }
+ o.removeEventListener("tabFocusEnabledChange", tabFocusEnabledChangeHandler);
+ o.removeEventListener("tabIndexChange", tabIndexChangeHandler);
+ }
+ removeFocusables(o, false);
+ }
+
+ /**
+ * @private
+ */
+ private function removeFocusables(o:DisplayObject, dontRemoveTabChildrenHandler:Boolean):void
+ {
+ var i:int;
+ if (o is DisplayObjectContainer)
+ {
+ if (!dontRemoveTabChildrenHandler)
+ {
+ o.removeEventListener("tabChildrenChange", tabChildrenChangeHandler);
+ o.removeEventListener("hasFocusableChildrenChange", hasFocusableChildrenChangeHandler);
+ }
+
+ for (i = 0; i < focusableObjects.length; i++)
+ {
+ if (isParent(DisplayObjectContainer(o), focusableObjects[i]))
+ {
+ if (focusableObjects[i] == _lastFocus)
+ {
+ _lastFocus.drawFocus(false);
+ _lastFocus = null;
+ }
+ // trace("FM removed " + focusableObjects[i]);
+ focusableObjects[i].removeEventListener(
+ "tabFocusEnabledChange", tabFocusEnabledChangeHandler);
+ focusableObjects[i].removeEventListener(
+ "tabIndexChange", tabIndexChangeHandler);
+ focusableObjects.splice(i, 1);
+ i = i - 1; // because increment would skip one
+
+ focusableCandidates = [];
+ calculateCandidates = true;
+ }
+ }
+ }
+ }
+
+ /**
+ * @private
+ */
+ private function showHandler(event:Event):void
+ {
+ var awm:IActiveWindowManager =
+ IActiveWindowManager(form.systemManager.getImplementation("mx.managers::IActiveWindowManager"));
+ if (awm)
+ awm.activate(form); // build a message that does the equal
+ }
+
+ /**
+ * @private
+ */
+ private function hideHandler(event:Event):void
+ {
+ var awm:IActiveWindowManager =
+ IActiveWindowManager(form.systemManager.getImplementation("mx.managers::IActiveWindowManager"));
+ if (awm)
+ awm.deactivate(form); // build a message that does the equal
+ }
+
+ /**
+ * @private
+ */
+ private function childHideHandler(event:Event):void
+ {
+ var target:DisplayObject = DisplayObject(event.target);
+ // trace("FocusManager focusInHandler in = " + this._form.systemManager.loaderInfo.url);
+ // trace("FM " + this + " focusInHandler " + target);
+
+ if (lastFocus && !isEnabledAndVisible(DisplayObject(lastFocus)) && DisplayObject(form).stage)
+ {
+ DisplayObject(form).stage.focus = null;
+ lastFocus = null;
+ }
+ }
+
+ /**
+ * @private
+ */
+ private function viewHideHandler(event:Event):void
+ {
+ // Target is the active view that is about to be hidden
+ var target:DisplayObjectContainer = event.target as DisplayObjectContainer;
+ var lastFocusDO:DisplayObject = lastFocus as DisplayObject;
+
+ // If the lastFocus is in the view about to be hidden, clear focus
+ if (target && lastFocusDO && target.contains(lastFocusDO))
+ lastFocus = null;
+ }
+
+ /**
+ * @private
+ */
+ private function creationCompleteHandler(event:FlexEvent):void
+ {
+ var o:DisplayObject = DisplayObject(form);
+ if (o.parent && o.visible && !activated)
+ {
+ var awm:IActiveWindowManager =
+ IActiveWindowManager(form.systemManager.getImplementation("mx.managers::IActiveWindowManager"));
+ if (awm)
+ awm.activate(form); // build a message that does the equal
+ }
+ }
+
+ /**
+ * @private
+ * Add or remove if tabbing properties change.
+ */
+ private function tabIndexChangeHandler(event:Event):void
+ {
+ calculateCandidates = true;
+ }
+
+ /**
+ * @private
+ * Add or remove if tabbing properties change.
+ */
+ private function tabFocusEnabledChangeHandler(event:Event):void
+ {
+ calculateCandidates = true;
+
+ var o:IFocusManagerComponent = IFocusManagerComponent(event.target);
+ var n:int = focusableObjects.length;
+ for (var i:int = 0; i < n; i++)
+ {
+ if (focusableObjects[i] == o)
+ break;
+ }
+ if (o.tabFocusEnabled)
+ {
+ if (i == n && isTabVisible(DisplayObject(o)))
+ {
+ // trace("FM tpc added " + o);
+ // add it if were not already
+ if (focusableObjects.indexOf(o) == -1)
+ focusableObjects.push(o);
+ }
+ }
+ else
+ {
+ // remove it
+ if (i < n)
+ {
+ // trace("FM tpc removed " + o);
+ focusableObjects.splice(i, 1);
+ }
+ }
+ }
+
+ /**
+ * @private
+ * Add or remove if tabbing properties change.
+ */
+ private function tabChildrenChangeHandler(event:Event):void
+ {
+ if (event.target != event.currentTarget)
+ return;
+
+ calculateCandidates = true;
+
+ var o:DisplayObjectContainer = DisplayObjectContainer(event.target);
+ if (o.tabChildren)
+ {
+ addFocusables(o, true);
+ }
+ else
+ {
+ removeFocusables(o, true);
+ }
+ }
+
+ /**
+ * @private
+ * Add or remove if tabbing properties change.
+ */
+ private function hasFocusableChildrenChangeHandler(event:Event):void
+ {
+ if (event.target != event.currentTarget)
+ return;
+
+ calculateCandidates = true;
+
+ var o:IFocusManagerComponent = IFocusManagerComponent(event.target);
+ if (o.hasFocusableChildren)
+ {
+ addFocusables(DisplayObject(o), true);
+ }
+ else
+ {
+ removeFocusables(DisplayObject(o), true);
+ }
+ }
+
+ /**
+ * @private
+ * This gets called when mouse clicks on a focusable object.
+ * We block player behavior
+ */
+ private function mouseFocusChangeHandler(event:FocusEvent):void
+ {
+ // trace("FocusManager: mouseFocusChangeHandler in = " + this._form.systemManager.loaderInfo.url);
+ // trace("FocusManager: mouseFocusChangeHandler " + event);
+
+ if (event.isDefaultPrevented())
+ return;
+
+ // If relatedObject is null because we don't have access to the
+ // object getting focus then allow the Player to set focus
+ // to the object. The isRelatedObjectInaccessible property is
+ // Player 10 only so we have to test if it is available. We
+ // will only see isRelatedObjectInaccessible if we are a version "10" swf
+ // (-target-player=10). Version "9" swfs will not see the property
+ // even if running in Player 10.
+ if (event.relatedObject == null &&
+ "isRelatedObjectInaccessible" in event &&
+ event["isRelatedObjectInaccessible"] == true)
+ {
+ // lost focus to a control in different sandbox.
+ return;
+ }
+
+ if (event.relatedObject is TextField)
+ {
+ var tf:TextField = event.relatedObject as TextField;
+ if (tf.type == "input" || tf.selectable)
+ {
+ return; // pass it on
+ }
+ }
+
+ event.preventDefault();
+ }
+
+ /**
+ * @private
+ * This gets called when the tab key is hit.
+ */
+ mx_internal function keyFocusChangeHandler(event:FocusEvent):void
+ {
+ // trace("keyFocusChangeHandler handled by " + this);
+ // trace("keyFocusChangeHandler event = " + event);
+
+ var sm:ISystemManager = form.systemManager;
+
+ if (hasEventListener("keyFocusChange"))
+ if (!dispatchEvent(new FocusEvent("keyFocusChange", false, true, InteractiveObject(event.target))))
+ return;
+
+ showFocusIndicator = true;
+ focusChanged = false;
+
+ var haveBrowserFocusComponent:Boolean = (browserFocusComponent != null);
+ if (browserFocusComponent)
+ clearBrowserFocusComponent();
+
+ // see if we got here from a tab. We also need to check for
+ // keyCode == 0 because in IE sometimes the first time you tab
+ // in to the flash player, you get keyCode == 0 instead of TAB.
+ // Flash Player bug #2295688.
+ if ((event.keyCode == Keyboard.TAB || (browserMode && event.keyCode == 0))
+ && !event.isDefaultPrevented())
+ {
+ if (haveBrowserFocusComponent)
+ {
+ if (hasEventListener("browserFocusComponent"))
+ dispatchEvent(new FocusEvent("browserFocusComponent", false, false, InteractiveObject(event.target)));
+
+ return;
+ }
+
+ if (ieshifttab && lastAction == "ACTIVATE")
+ {
+ // IE seems to now require that we set focus to something during activate
+ // but then we get this keyFocusChange event. I think we used to not
+ // need to set focus on activate and we still got the keyFocusChange
+ // and then stage.focus was null and we'd use the keyFocusChange event
+ // to determine which control (first or last) got focus based on
+ // the shift key.
+ // If we set focus on activate, then we get this keyFocusChange which moves
+ // the focus somewhere else, so we set fauxFocus to the stage as a signal
+ // to the setFocusToNextObject logic that it shouldn't use the stage.focus
+ // as the starting point.
+ fauxFocus = sm.stage;
+ }
+ // trace("tabHandled by " + this);
+ setFocusToNextObject(event);
+ if (ieshifttab && lastAction == "ACTIVATE")
+ {
+ fauxFocus = null;
+ }
+
+ // if we changed focus or if we're the main app
+ // eat the event
+ if (focusChanged || sm == sm.getTopLevelRoot())
+ event.preventDefault();
+ }
+ }
+
+ /**
+ * @private
+ * Watch for TAB keys.
+ */
+ mx_internal function keyDownHandler(event:KeyboardEvent):void
+ {
+ // trace("onKeyDown handled by " + this);
+ // trace("onKeyDown event = " + event);
+ // if the target is in a bridged application, let it handle the click.
+ var sm:ISystemManager = form.systemManager;
+
+ if (hasEventListener("keyDownFM"))
+ if (!dispatchEvent(new FocusEvent("keyDownFM", false, true, InteractiveObject(event.target))))
+ return;
+
+ if (sm is SystemManager)
+ SystemManager(sm).idleCounter = 0;
+
+ if (event.keyCode == Keyboard.TAB)
+ {
+ lastAction = "KEY";
+
+ // I think we'll have time to do this here instead of at creation time
+ // this makes and orders the focusableCandidates array
+ if (calculateCandidates)
+ {
+ sortFocusableObjects();
+ calculateCandidates = false;
+ }
+ }
+
+ if (browserMode)
+ {
+ if (browserFocusComponent)
+ clearBrowserFocusComponent();
+
+ if (event.keyCode == Keyboard.TAB && focusableCandidates.length > 0)
+ {
+ // get the object that has the focus
+ var o:DisplayObject = fauxFocus;
+ if (!o)
+ {
+ o = form.systemManager.stage.focus;
+ }
+
+ // trace("focus was at " + o);
+ // trace("focusableObjects " + focusableObjects.length);
+ o = DisplayObject(findFocusManagerComponent2(InteractiveObject(o)));
+ var g:String = "";
+ if (o is IFocusManagerGroup)
+ {
+ var tg:IFocusManagerGroup = IFocusManagerGroup(o);
+ g = tg.groupName;
+ }
+
+ var i:int = getIndexOfFocusedObject(o);
+ var j:int = getIndexOfNextObject(i, event.shiftKey, false, g);
+ if (event.shiftKey)
+ {
+ if (j >= i)
+ {
+ // we wrapped so let browser have it
+ browserFocusComponent = getBrowserFocusComponent(event.shiftKey);
+ if (browserFocusComponent.tabIndex == -1)
+ browserFocusComponent.tabIndex = 0;
+ }
+ }
+ else
+ {
+ if (j <= i)
+ {
+ // we wrapped so let browser have it
+ browserFocusComponent = getBrowserFocusComponent(event.shiftKey);
+ if (browserFocusComponent.tabIndex == -1)
+ browserFocusComponent.tabIndex = LARGE_TAB_INDEX;
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * @private
+ * Watch for ENTER key.
+ */
+ private function defaultButtonKeyHandler(event:KeyboardEvent):void
+ {
+ var sm:ISystemManager = form.systemManager;
+ if (hasEventListener("defaultButtonKeyHandler"))
+ if (!dispatchEvent(new FocusEvent("defaultButtonKeyHandler", false, true)))
+ return;
+
+ if (defaultButtonEnabled && event.keyCode == Keyboard.ENTER &&
+ defButton && defButton.enabled)
+ {
+ sendDefaultButtonEvent();
+ }
+ }
+
+ /**
+ * @private
+ * This gets called when the focus changes due to a mouse click.
+ *
+ * Note: If the focus is changing to a TextField, we don't call
+ * setFocus() on it because the player handles it;
+ * calling setFocus() on a TextField which has scrollable text
+ * causes the text to autoscroll to the end, making the
+ * mouse click set the insertion point in the wrong place.
+ */
+ private function mouseDownCaptureHandler(event:MouseEvent):void
+ {
+ // trace("FocusManager mouseDownCaptureHandler in = " + this._form.systemManager.loaderInfo.url);
+ // trace("FocusManager mouseDownCaptureHandler target " + event.target);
+ showFocusIndicator = false;
+ }
+
+ /**
+ * @private
+ * This gets called when the focus changes due to a mouse click.
+ *
+ * Note: If the focus is changing to a TextField, we don't call
+ * setFocus() on it because the player handles it;
+ * calling setFocus() on a TextField which has scrollable text
+ * causes the text to autoscroll to the end, making the
+ * mouse click set the insertion point in the wrong place.
+ */
+ private function mouseDownHandler(event:MouseEvent):void
+ {
+ // trace("FocusManager mouseDownHandler in = " + this._form.systemManager.loaderInfo.url);
+ // trace("FocusManager mouseDownHandler target " + event.target);
+
+ // if the target is in a bridged application, let it handle the click.
+ var sm:ISystemManager = form.systemManager;
+ var o:DisplayObject = getTopLevelFocusTarget(
+ InteractiveObject(event.target));
+
+ if (!o)
+ return;
+
+ // trace("FocusManager mouseDownHandler on " + o);
+
+ // Make sure the containing component gets notified.
+ // As the note above says, we don't set focus to a TextField ever
+ // because the player already did and took care of where
+ // the insertion point is, and we also don't call setfocus
+ // on a component that last the last focused object unless
+ // the last action was just to activate the player and didn't
+ // involve tabbing or clicking on a component
+ if ((o != _lastFocus || lastAction == "ACTIVATE") && !(o is TextField))
+ setFocus(IFocusManagerComponent(o));
+ else if (_lastFocus)
+ {
+ // trace("FM: skipped setting focus to " + _lastFocus);
+ }
+
+ if (hasEventListener("mouseDownFM"))
+ dispatchEvent(new FocusEvent("mouseDownFM", false, false, InteractiveObject(o)));
+
+ lastAction = "MOUSEDOWN";
+
+ }
+
+ private function getBrowserFocusComponent(shiftKey:Boolean):InteractiveObject
+ {
+ var focusComponent:InteractiveObject = form.systemManager.stage.focus;
+
+ // if the focus is null it means focus is in an application we
+ // don't have access to. Use either the last object or the first
+ // object in this focus manager's list.
+ if (!focusComponent)
+ {
+ var index:int = shiftKey ? 0 : focusableCandidates.length - 1;
+ focusComponent = focusableCandidates[index];
+ }
+
+ return focusComponent;
+ }
+}
+
+}
+
+import flash.display.DisplayObject;
+
+/**
+ * @private
+ *
+ * Plain old class to return multiple items of info about the potential
+ * change in focus.
+ */
+class FocusInfo
+{
+ public var displayObject:DisplayObject; // object to get focus
+ public var wrapped:Boolean; // true if focus wrapped around
+}
http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/4f3802ef/frameworks/projects/MX/src/main/flex/mx/managers/IFocusManagerComplexComponent.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/MX/src/main/flex/mx/managers/IFocusManagerComplexComponent.as b/frameworks/projects/MX/src/main/flex/mx/managers/IFocusManagerComplexComponent.as
new file mode 100644
index 0000000..c6400ee
--- /dev/null
+++ b/frameworks/projects/MX/src/main/flex/mx/managers/IFocusManagerComplexComponent.as
@@ -0,0 +1,82 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package mx.managers
+{
+
+/**
+ * The IFocusManagerComplexComponent interface defines the interface
+ * that components that can have more than one internal focus target
+ * should implement in order to
+ * receive focus from the FocusManager.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+public interface IFocusManagerComplexComponent extends IFocusManagerComponent
+{
+ //--------------------------------------------------------------------------
+ //
+ // Properties
+ //
+ //--------------------------------------------------------------------------
+
+ //----------------------------------
+ // hasFocusableContent
+ //----------------------------------
+
+ /**
+ * A flag that indicates whether the component currently has internal
+ * focusable targets
+ *
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ function get hasFocusableContent():Boolean;
+
+ //--------------------------------------------------------------------------
+ //
+ // Methods
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Called by the FocusManager when the component receives focus.
+ * The component may in turn set focus to an internal component.
+ * The components setFocus() method will still be called when focused by
+ * the mouse, but this method will be used when focus changes via the
+ * keyboard
+ *
+ * @param direction "bottom" if TAB used with SHIFT key, "top" otherwise
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ function assignFocus(direction:String):void;
+
+}
+
+}
http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/4f3802ef/frameworks/projects/MX/src/main/flex/mx/managers/IFocusManagerGroup.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/MX/src/main/flex/mx/managers/IFocusManagerGroup.as b/frameworks/projects/MX/src/main/flex/mx/managers/IFocusManagerGroup.as
new file mode 100644
index 0000000..97192bd
--- /dev/null
+++ b/frameworks/projects/MX/src/main/flex/mx/managers/IFocusManagerGroup.as
@@ -0,0 +1,85 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package mx.managers
+{
+
+/**
+ * The IFocusManagerGroup interface defines the interface that
+ * any component must implement if it is grouped in sets,
+ * where only one member of the set can be selected at any given time.
+ * For example, a RadioButton implements IFocusManagerGroup
+ * because a set of RadioButtons in the same group
+ * can only have one RadioButton selected at any one time,
+ * and the FocusManager will make sure not to give focus to the RadioButtons
+ * that are not selected in response to moving focus via the Tab key.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+public interface IFocusManagerGroup
+{
+ //--------------------------------------------------------------------------
+ //
+ // Properties
+ //
+ //--------------------------------------------------------------------------
+
+ //----------------------------------
+ // groupName
+ //----------------------------------
+
+ /**
+ * The name of the group of controls to which the control belongs.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ function get groupName():String;
+
+ /**
+ * @private
+ */
+ function set groupName(value:String):void;
+
+ //----------------------------------
+ // selected
+ //----------------------------------
+
+ /**
+ * A flag that indicates whether this control is selected.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ function get selected():Boolean;
+
+ /**
+ * @private
+ */
+ function set selected(value:Boolean):void;
+}
+
+}
http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/4f3802ef/frameworks/projects/MX/src/main/flex/mx/managers/ISystemManager.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/MX/src/main/flex/mx/managers/ISystemManager.as b/frameworks/projects/MX/src/main/flex/mx/managers/ISystemManager.as
index 072c0cc..35e5800 100644
--- a/frameworks/projects/MX/src/main/flex/mx/managers/ISystemManager.as
+++ b/frameworks/projects/MX/src/main/flex/mx/managers/ISystemManager.as
@@ -24,6 +24,7 @@ COMPILE::AS3
{
import flash.display.DisplayObject;
import flash.display.Sprite;
+ import flash.display.Stage;
}
COMPILE::JS
{
@@ -506,6 +507,23 @@ public interface ISystemManager extends IEventDispatcher, IChildList, IFlexModul
*/
function invalidateParentSizeAndDisplayList():void;
+
+ //----------------------------------
+ // stage
+ //----------------------------------
+
+ /**
+ * The flash.display.Stage that represents the application window
+ * mapped to this SystemManager
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 3
+ */
+ COMPILE::AS3
+ function get stage():Stage
+
}
}
http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/4f3802ef/frameworks/projects/MX/src/main/flex/mx/states/AddItems.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/MX/src/main/flex/mx/states/AddItems.as b/frameworks/projects/MX/src/main/flex/mx/states/AddItems.as
index 68be25a..3254346 100644
--- a/frameworks/projects/MX/src/main/flex/mx/states/AddItems.as
+++ b/frameworks/projects/MX/src/main/flex/mx/states/AddItems.as
@@ -38,7 +38,7 @@ import mx.core.IDeferredContentOwner;
import mx.core.IMXMLObject;
import mx.core.ITransientDeferredInstance;
import mx.core.IUIComponent;
-import mx.core.IVisualElement;
+import org.apache.flex.core.IVisualElement;
import mx.core.IVisualElementContainer;
import mx.core.UIComponent;