PageRenderTime 50ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 1ms

/Sample/mx/managers/FocusManager.as

https://github.com/ingydotnet/yaml-oscon2009-talk
ActionScript | 2257 lines | 1255 code | 303 blank | 699 comment | 285 complexity | 7ecbf0c83d17c85905c9c9898cb515da MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. ////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // ADOBE SYSTEMS INCORPORATED
  4. // Copyright 2003-2007 Adobe Systems Incorporated
  5. // All Rights Reserved.
  6. //
  7. // NOTICE: Adobe permits you to use, modify, and distribute this file
  8. // in accordance with the terms of the license agreement accompanying it.
  9. //
  10. ////////////////////////////////////////////////////////////////////////////////
  11. package mx.managers
  12. {
  13. import flash.display.DisplayObject;
  14. import flash.display.DisplayObjectContainer;
  15. import flash.display.InteractiveObject;
  16. import flash.display.LoaderInfo;
  17. import flash.display.Sprite;
  18. import flash.events.Event;
  19. import flash.events.FocusEvent;
  20. import flash.events.IEventDispatcher;
  21. import flash.events.KeyboardEvent;
  22. import flash.events.MouseEvent;
  23. import flash.system.Capabilities;
  24. import flash.text.TextField;
  25. import flash.ui.Keyboard;
  26. import flash.utils.Dictionary;
  27. import mx.core.Application;
  28. import mx.core.FlexSprite;
  29. import mx.core.ISWFLoader;
  30. import mx.core.IButton;
  31. import mx.core.IChildList;
  32. import mx.core.IRawChildrenContainer;
  33. import mx.core.ISWFBridgeProvider;
  34. import mx.core.IUIComponent;
  35. import mx.core.mx_internal;
  36. import mx.core.SWFBridgeGroup;
  37. import mx.events.FlexEvent;
  38. import mx.events.FocusRequestDirection;
  39. import mx.events.SWFBridgeEvent;
  40. import mx.events.SWFBridgeRequest;
  41. import mx.utils.DisplayUtil;
  42. use namespace mx_internal;
  43. /**
  44. * The FocusManager class manages the focus on components in response to mouse
  45. * activity or keyboard activity (Tab key). There can be several FocusManager
  46. * instances in an application. Each FocusManager instance
  47. * is responsible for a set of components that comprise a "tab loop". If you
  48. * hit Tab enough times, focus traverses through a set of components and
  49. * eventually get back to the first component that had focus. That is a "tab loop"
  50. * and a FocusManager instance manages that loop. If there are popup windows
  51. * with their own set of components in a "tab loop" those popup windows will have
  52. * their own FocusManager instances. The main application always has a
  53. * FocusManager instance.
  54. *
  55. * <p>The FocusManager manages focus from the "component level".
  56. * In Flex, a UITextField in a component is the only way to allow keyboard entry
  57. * of text. To the Flash Player or AIR, that UITextField has focus. However, from the
  58. * FocusManager's perspective the component that parents the UITextField has focus.
  59. * Thus there is a distinction between component-level focus and player-level focus.
  60. * Application developers generally only have to deal with component-level focus while
  61. * component developers must understand player-level focus.</p>
  62. *
  63. * <p>All components that can be managed by the FocusManager must implement
  64. * mx.managers.IFocusManagerComponent, whereas objects managed by player-level focus do not.</p>
  65. *
  66. * <p>The FocusManager also managers the concept of a defaultButton, which is
  67. * the Button on a form that dispatches a click event when the Enter key is pressed
  68. * depending on where focus is at that time.</p>
  69. */
  70. public class FocusManager implements IFocusManager
  71. {
  72. include "../core/Version.as";
  73. //--------------------------------------------------------------------------
  74. //
  75. // Class constants
  76. //
  77. //--------------------------------------------------------------------------
  78. /**
  79. * @private
  80. *
  81. * Default value of parameter, ignore.
  82. */
  83. private static const FROM_INDEX_UNSPECIFIED:int = -2;
  84. //--------------------------------------------------------------------------
  85. //
  86. // Constructor
  87. //
  88. //--------------------------------------------------------------------------
  89. /**
  90. * Constructor.
  91. *
  92. * <p>A FocusManager manages the focus within the children of an IFocusManagerContainer.
  93. * It installs itself in the IFocusManagerContainer during execution
  94. * of the constructor.</p>
  95. *
  96. * @param container An IFocusManagerContainer that hosts the FocusManager.
  97. *
  98. * @param popup If <code>true</code>, indicates that the container
  99. * is a popup component and not the main application.
  100. */
  101. public function FocusManager(container:IFocusManagerContainer, popup:Boolean = false)
  102. {
  103. super();
  104. this.popup = popup;
  105. browserMode = Capabilities.playerType == "ActiveX" && !popup;
  106. container.focusManager = this; // this property name is reserved in the parent
  107. // trace("FocusManager constructor " + container + ".focusManager");
  108. _form = container;
  109. focusableObjects = [];
  110. focusPane = new FlexSprite();
  111. focusPane.name = "focusPane";
  112. addFocusables(DisplayObject(container));
  113. // Listen to the stage so we know when the root application is loaded.
  114. container.addEventListener(Event.ADDED, addedHandler);
  115. container.addEventListener(Event.REMOVED, removedHandler);
  116. container.addEventListener(FlexEvent.SHOW, showHandler);
  117. container.addEventListener(FlexEvent.HIDE, hideHandler);
  118. //special case application and window
  119. if (container.systemManager is SystemManager)
  120. {
  121. // special case application. It shouldn't need to be made
  122. // active and because we defer appCreationComplete, this
  123. // would steal focus back from any popups created during
  124. // instantiation
  125. if (container != SystemManager(container.systemManager).application)
  126. container.addEventListener(FlexEvent.CREATION_COMPLETE,
  127. creationCompleteHandler);
  128. }
  129. // Make sure the SystemManager is running so it can tell us about
  130. // mouse clicks and stage size changes.
  131. try
  132. {
  133. container.systemManager.addFocusManager(container); // build a message that does the equal
  134. var sm:ISystemManager = form.systemManager;
  135. // Set up our swfBridgeGroup. If this is a pop up then the parent
  136. // bridge is empty, otherwise its the form's system manager's bridge.
  137. swfBridgeGroup = new SWFBridgeGroup(sm);
  138. if (!popup)
  139. swfBridgeGroup.parentBridge = sm.swfBridgeGroup.parentBridge;
  140. // add ourselves to our parent focus manager if this is a bridged
  141. // application not a dialog or other popup.
  142. if (sm.useSWFBridge())
  143. {
  144. sm.addEventListener(SWFBridgeEvent.BRIDGE_APPLICATION_UNLOADING, removeFromParentBridge);
  145. // have the child listen to move requests from the parent.
  146. var bridge:IEventDispatcher = swfBridgeGroup.parentBridge;
  147. if (bridge)
  148. {
  149. bridge.addEventListener(SWFBridgeRequest.MOVE_FOCUS_REQUEST, focusRequestMoveHandler);
  150. bridge.addEventListener(SWFBridgeRequest.SET_SHOW_FOCUS_INDICATOR_REQUEST,
  151. setShowFocusIndicatorRequestHandler);
  152. }
  153. // add listener activate/deactivate requests
  154. if (bridge && !(form.systemManager is SystemManagerProxy))
  155. {
  156. bridge.addEventListener(SWFBridgeRequest.ACTIVATE_FOCUS_REQUEST, focusRequestActivateHandler);
  157. bridge.addEventListener(SWFBridgeRequest.DEACTIVATE_FOCUS_REQUEST, focusRequestDeactivateHandler);
  158. bridge.addEventListener(SWFBridgeEvent.BRIDGE_FOCUS_MANAGER_ACTIVATE,
  159. bridgeEventActivateHandler);
  160. }
  161. // listen when the container has been added to the stage so we can add the focusable
  162. // children
  163. container.addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
  164. }
  165. }
  166. catch (e:Error)
  167. {
  168. // ignore null pointer errors caused by container using a
  169. // systemManager from another sandbox.
  170. }
  171. }
  172. //--------------------------------------------------------------------------
  173. //
  174. // Variables
  175. //
  176. //--------------------------------------------------------------------------
  177. private var LARGE_TAB_INDEX:int = 99999;
  178. private var calculateCandidates:Boolean = true;
  179. /**
  180. * @private
  181. * We track whether we've been last activated or saw a TAB
  182. * This is used in browser tab management
  183. */
  184. private var lastAction:String;
  185. /**
  186. * @private
  187. * Tab management changes based on whether were in a browser or not
  188. * This value is also affected by whether you are a modal dialog or not
  189. */
  190. public var browserMode:Boolean;
  191. /**
  192. * @private
  193. * Tab management changes based on whether were in a browser or not
  194. * If non-null, this is the object that will
  195. * lose focus to the browser
  196. */
  197. private var browserFocusComponent:InteractiveObject;
  198. /**
  199. * @private
  200. * Total set of all objects that can receive focus
  201. * but might be disabled or invisible.
  202. */
  203. private var focusableObjects:Array;
  204. /**
  205. * @private
  206. * Filtered set of objects that can receive focus right now.
  207. */
  208. private var focusableCandidates:Array;
  209. /**
  210. * @private
  211. */
  212. private var activated:Boolean = false;
  213. /**
  214. * @private
  215. *
  216. * true if focus was changed to one of focusable objects. False if focus passed to
  217. * the browser.
  218. */
  219. private var focusChanged:Boolean;
  220. /**
  221. * @private
  222. *
  223. * if non-null, the location to move focus from instead of the object
  224. * that has focus in the stage.
  225. */
  226. private var fauxFocus:DisplayObject;
  227. /**
  228. * @private
  229. *
  230. * The focus manager maintains its own bridges so a focus manager in a pop
  231. * up can move focus to another focus manager in the same pop up. That is,
  232. * A pop ups can be a collection of focus managers working together just
  233. * as is done in the System Manager's document.
  234. */
  235. private var swfBridgeGroup:SWFBridgeGroup;
  236. /**
  237. * @private
  238. *
  239. * bridge handle of the last active focus manager.
  240. */
  241. private var lastActiveFocusManager:FocusManager;
  242. /**
  243. * @private
  244. *
  245. * Test if the focus was set locally in this focus manager (true) or
  246. * if focus was transfer to another focus manager (false)
  247. */
  248. private var focusSetLocally:Boolean;
  249. /**
  250. * @private
  251. *
  252. * True if this focus manager is a popup, false if it is a main application.
  253. *
  254. */
  255. private var popup:Boolean;
  256. /**
  257. * @private
  258. *
  259. * Used when a the skip parameter can't be passed into
  260. * dispatchEventFromSWFBridges() because the caller doesn't take
  261. * a skip parameter.
  262. */
  263. private var skipBridge:IEventDispatcher;
  264. //--------------------------------------------------------------------------
  265. //
  266. // Properties
  267. //
  268. //--------------------------------------------------------------------------
  269. //----------------------------------
  270. // showFocusIndicator
  271. //----------------------------------
  272. /**
  273. * @private
  274. * Storage for the showFocusIndicator property.
  275. */
  276. private var _showFocusIndicator:Boolean = false;
  277. /**
  278. * @inheritDoc
  279. */
  280. public function get showFocusIndicator():Boolean
  281. {
  282. return _showFocusIndicator;
  283. }
  284. /**
  285. * @private
  286. */
  287. public function set showFocusIndicator(value:Boolean):void
  288. {
  289. var changed:Boolean = _showFocusIndicator != value;
  290. _showFocusIndicator = value;
  291. if (changed && !popup && form.systemManager.swfBridgeGroup)
  292. dispatchSetShowFocusIndicatorRequest(value, null);
  293. }
  294. //----------------------------------
  295. // defaultButton
  296. //----------------------------------
  297. /**
  298. * @private
  299. * The current default button.
  300. */
  301. private var defButton:IButton;
  302. /**
  303. * @private
  304. */
  305. private var _defaultButton:IButton;
  306. /**
  307. * @inheritDoc
  308. */
  309. public function get defaultButton():IButton
  310. {
  311. return _defaultButton;
  312. }
  313. /**
  314. * @private
  315. * We don't type the value as Button for dependency reasons
  316. */
  317. public function set defaultButton(value:IButton):void
  318. {
  319. var button:IButton = value ? IButton(value) : null;
  320. if (button != _defaultButton)
  321. {
  322. if (_defaultButton)
  323. _defaultButton.emphasized = false;
  324. if (defButton)
  325. defButton.emphasized = false;
  326. _defaultButton = button;
  327. defButton = button;
  328. if (button)
  329. button.emphasized = true;
  330. }
  331. }
  332. //----------------------------------
  333. // defaultButtonEnabled
  334. //----------------------------------
  335. /**
  336. * @private
  337. * Storage for the defaultButtonEnabled property.
  338. */
  339. private var _defaultButtonEnabled:Boolean = true;
  340. /**
  341. * @inheritDoc
  342. */
  343. public function get defaultButtonEnabled():Boolean
  344. {
  345. return _defaultButtonEnabled;
  346. }
  347. /**
  348. * @private
  349. */
  350. public function set defaultButtonEnabled(value:Boolean):void
  351. {
  352. _defaultButtonEnabled = value;
  353. }
  354. //----------------------------------
  355. // focusPane
  356. //----------------------------------
  357. /**
  358. * @private
  359. * Storage for the focusPane property.
  360. */
  361. private var _focusPane:Sprite;
  362. /**
  363. * @inheritDoc
  364. */
  365. public function get focusPane():Sprite
  366. {
  367. return _focusPane;
  368. }
  369. /**
  370. * @private
  371. */
  372. public function set focusPane(value:Sprite):void
  373. {
  374. _focusPane = value;
  375. }
  376. //----------------------------------
  377. // form
  378. //----------------------------------
  379. /**
  380. * @private
  381. * Storage for the form property.
  382. */
  383. private var _form:IFocusManagerContainer;
  384. /**
  385. * @private
  386. * The form is the property where we store the IFocusManagerContainer
  387. * that hosts this FocusManager.
  388. */
  389. mx_internal function get form():IFocusManagerContainer
  390. {
  391. return _form;
  392. }
  393. /**
  394. * @private
  395. */
  396. mx_internal function set form (value:IFocusManagerContainer):void
  397. {
  398. _form = value;
  399. }
  400. //----------------------------------
  401. // _lastFocus
  402. //----------------------------------
  403. /**
  404. * @private
  405. * the object that last had focus
  406. */
  407. private var _lastFocus:IFocusManagerComponent;
  408. /**
  409. * @private
  410. */
  411. mx_internal function get lastFocus():IFocusManagerComponent
  412. {
  413. return _lastFocus;
  414. }
  415. //----------------------------------
  416. // nextTabIndex
  417. //----------------------------------
  418. /**
  419. * @inheritDoc
  420. */
  421. public function get nextTabIndex():int
  422. {
  423. return getMaxTabIndex() + 1;
  424. }
  425. /**
  426. * Gets the highest tab index currently used in this Focus Manager's form or subform.
  427. *
  428. * @return Highest tab index currently used.
  429. */
  430. private function getMaxTabIndex():int
  431. {
  432. var z:Number = 0;
  433. var n:int = focusableObjects.length;
  434. for (var i:int = 0; i < n; i++)
  435. {
  436. var t:Number = focusableObjects[i].tabIndex;
  437. if (!isNaN(t))
  438. z = Math.max(z, t);
  439. }
  440. return z;
  441. }
  442. //--------------------------------------------------------------------------
  443. //
  444. // Methods
  445. //
  446. //--------------------------------------------------------------------------
  447. /**
  448. * @inheritDoc
  449. */
  450. public function getFocus():IFocusManagerComponent
  451. {
  452. var o:InteractiveObject = form.systemManager.stage.focus;
  453. return findFocusManagerComponent(o);
  454. }
  455. /**
  456. * @inheritDoc
  457. */
  458. public function setFocus(o:IFocusManagerComponent):void
  459. {
  460. // trace("FM " + this + " setting focus to " + o);
  461. o.setFocus();
  462. focusSetLocally = true;
  463. // trace("FM set focus");
  464. }
  465. /**
  466. * @private
  467. */
  468. private function focusInHandler(event:FocusEvent):void
  469. {
  470. var target:InteractiveObject = InteractiveObject(event.target);
  471. // trace("FocusManager focusInHandler in = " + this._form.systemManager.loaderInfo.url);
  472. // trace("FM " + this + " focusInHandler " + target);
  473. // if the target is in a bridged application, let it handle the click.
  474. var sm:ISystemManager = form.systemManager;
  475. if (sm.isDisplayObjectInABridgedApplication(DisplayObject(event.target)))
  476. return;
  477. if (isParent(DisplayObjectContainer(form), target))
  478. {
  479. // trace("FM " + this + " setting last focus " + target);
  480. _lastFocus = findFocusManagerComponent(InteractiveObject(target));
  481. // handle default button here
  482. // we can't check for Button because of cross-versioning so
  483. // for now we just check for an emphasized property
  484. if (_lastFocus is IButton)
  485. {
  486. var x:IButton = _lastFocus as IButton;
  487. // if we have marked some other button as a default button
  488. if (defButton)
  489. {
  490. // change it to be this button
  491. defButton.emphasized = false;
  492. defButton = x;
  493. x.emphasized = true;
  494. }
  495. }
  496. else
  497. {
  498. // restore the default button to be the original one
  499. if (defButton && defButton != _defaultButton)
  500. {
  501. defButton.emphasized = false;
  502. defButton = _defaultButton;
  503. _defaultButton.emphasized = true;
  504. }
  505. }
  506. }
  507. }
  508. /**
  509. * @private Useful for debugging
  510. */
  511. private function focusOutHandler(event:FocusEvent):void
  512. {
  513. var target:InteractiveObject = InteractiveObject(event.target);
  514. // trace("FocusManager focusOutHandler in = " + this._form.systemManager.loaderInfo.url);
  515. // trace("FM " + this + " focusOutHandler " + target);
  516. }
  517. /**
  518. * @private
  519. * restore focus to whoever had it last
  520. */
  521. private function activateHandler(event:Event):void
  522. {
  523. // var target:InteractiveObject = InteractiveObject(event.target);
  524. // trace("FM " + this + " activateHandler ", _lastFocus);
  525. // restore focus if this focus manager had last focus
  526. if (_lastFocus && !browserMode)
  527. _lastFocus.setFocus();
  528. lastAction = "ACTIVATE";
  529. }
  530. /**
  531. * @private Useful for debugging
  532. */
  533. private function deactivateHandler(event:Event):void
  534. {
  535. // var target:InteractiveObject = InteractiveObject(event.target);
  536. // trace("FM " + this + " deactivateHandler ", _lastFocus);
  537. }
  538. /**
  539. * @inheritDoc
  540. */
  541. public function showFocus():void
  542. {
  543. if (!showFocusIndicator)
  544. {
  545. showFocusIndicator = true;
  546. if (_lastFocus)
  547. _lastFocus.drawFocus(true);
  548. }
  549. }
  550. /**
  551. * @inheritDoc
  552. */
  553. public function hideFocus():void
  554. {
  555. // trace("FOcusManger " + this + " Hide Focus");
  556. if (showFocusIndicator)
  557. {
  558. showFocusIndicator = false;
  559. if (_lastFocus)
  560. _lastFocus.drawFocus(false);
  561. }
  562. // trace("END FOcusManger Hide Focus");
  563. }
  564. /**
  565. * The SystemManager activates and deactivates a FocusManager
  566. * if more than one IFocusManagerContainer is visible at the same time.
  567. * If the mouse is clicked in an IFocusManagerContainer with a deactivated
  568. * FocusManager, the SystemManager will call
  569. * the <code>activate()</code> method on that FocusManager.
  570. * The FocusManager that was activated will have its <code>deactivate()</code> method
  571. * called prior to the activation of another FocusManager.
  572. *
  573. * <p>The FocusManager adds event handlers that allow it to monitor
  574. * focus related keyboard and mouse activity.</p>
  575. */
  576. public function activate():void
  577. {
  578. // we can get a double activation if we're popping up and becoming visible
  579. // like the second time a menu appears
  580. if (activated)
  581. {
  582. // trace("FocusManager is already active " + this);
  583. return;
  584. }
  585. //trace("FocusManager activating = " + this._form.systemManager.loaderInfo.url);
  586. //trace("FocusManager activating " + this);
  587. // listen for focus changes, use weak references for the stage
  588. // form.systemManager can be null if the form is created in a sandbox and
  589. // added as a child to the root system manager.
  590. var sm:ISystemManager = form.systemManager;
  591. if (sm)
  592. {
  593. if (sm.isTopLevelRoot())
  594. {
  595. sm.stage.addEventListener(FocusEvent.MOUSE_FOCUS_CHANGE, mouseFocusChangeHandler, false, 0, true);
  596. sm.stage.addEventListener(FocusEvent.KEY_FOCUS_CHANGE, keyFocusChangeHandler, false, 0, true);
  597. sm.stage.addEventListener(Event.ACTIVATE, activateHandler, false, 0, true);
  598. sm.stage.addEventListener(Event.DEACTIVATE, deactivateHandler, false, 0, true);
  599. }
  600. else
  601. {
  602. sm.addEventListener(FocusEvent.MOUSE_FOCUS_CHANGE, mouseFocusChangeHandler, false, 0, true);
  603. sm.addEventListener(FocusEvent.KEY_FOCUS_CHANGE, keyFocusChangeHandler, false, 0, true);
  604. sm.addEventListener(Event.ACTIVATE, activateHandler, false, 0, true);
  605. sm.addEventListener(Event.DEACTIVATE, deactivateHandler, false, 0, true);
  606. }
  607. }
  608. form.addEventListener(FocusEvent.FOCUS_IN, focusInHandler, true);
  609. form.addEventListener(FocusEvent.FOCUS_OUT, focusOutHandler, true);
  610. form.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
  611. form.addEventListener(KeyboardEvent.KEY_DOWN, defaultButtonKeyHandler);
  612. // listen for default button in Capture phase. Some components like TextInput
  613. // and Accordion stop the Enter key from propagating in the Bubble phase.
  614. form.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler, true);
  615. activated = true;
  616. // Restore focus to the last control that had it if there was one.
  617. if (_lastFocus)
  618. setFocus(_lastFocus);
  619. // activate children in compatibility mode or in sandboxes.
  620. dispatchEventFromSWFBridges(new SWFBridgeRequest(SWFBridgeRequest.ACTIVATE_FOCUS_REQUEST), skipBridge);
  621. }
  622. /**
  623. * The SystemManager activates and deactivates a FocusManager
  624. * if more than one IFocusManagerContainer is visible at the same time.
  625. * If the mouse is clicked in an IFocusManagerContainer with a deactivated
  626. * FocusManager, the SystemManager will call
  627. * the <code>activate()</code> method on that FocusManager.
  628. * The FocusManager that was activated will have its <code>deactivate()</code> method
  629. * called prior to the activation of another FocusManager.
  630. *
  631. * <p>The FocusManager removes event handlers that allow it to monitor
  632. * focus related keyboard and mouse activity.</p>
  633. */
  634. public function deactivate():void
  635. {
  636. // trace("FocusManager deactivating " + this);
  637. //trace("FocusManager deactivating = " + this._form.systemManager.loaderInfo.url);
  638. // listen for focus changes
  639. var sm:ISystemManager = form.systemManager;
  640. if (sm)
  641. {
  642. if (sm.isTopLevelRoot())
  643. {
  644. sm.stage.removeEventListener(FocusEvent.MOUSE_FOCUS_CHANGE, mouseFocusChangeHandler);
  645. sm.stage.removeEventListener(FocusEvent.KEY_FOCUS_CHANGE, keyFocusChangeHandler);
  646. sm.stage.removeEventListener(Event.ACTIVATE, activateHandler);
  647. sm.stage.removeEventListener(Event.DEACTIVATE, deactivateHandler);
  648. }
  649. else
  650. {
  651. sm.removeEventListener(FocusEvent.MOUSE_FOCUS_CHANGE, mouseFocusChangeHandler);
  652. sm.removeEventListener(FocusEvent.KEY_FOCUS_CHANGE, keyFocusChangeHandler);
  653. sm.removeEventListener(Event.ACTIVATE, activateHandler);
  654. sm.removeEventListener(Event.DEACTIVATE, deactivateHandler);
  655. }
  656. }
  657. form.removeEventListener(FocusEvent.FOCUS_IN, focusInHandler, true);
  658. form.removeEventListener(FocusEvent.FOCUS_OUT, focusOutHandler, true);
  659. form.removeEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
  660. form.removeEventListener(KeyboardEvent.KEY_DOWN, defaultButtonKeyHandler);
  661. // stop listening for default button in Capture phase
  662. form.removeEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler, true);
  663. activated = false;
  664. // deactivate children in compatibility mode or in sandboxes.
  665. dispatchEventFromSWFBridges(new SWFBridgeRequest(SWFBridgeRequest.DEACTIVATE_FOCUS_REQUEST), skipBridge);
  666. }
  667. /**
  668. * @inheritDoc
  669. */
  670. public function findFocusManagerComponent(
  671. o:InteractiveObject):IFocusManagerComponent
  672. {
  673. return findFocusManagerComponent2(o) as IFocusManagerComponent;
  674. }
  675. /**
  676. * @private
  677. *
  678. * This version of the method differs from the old one to support SWFLoader
  679. * being in the focusableObjects list but not being a component that
  680. * gets focus. SWFLoader is in the list of focusable objects so
  681. * focus may be passed over a bridge to the components on the other
  682. * side of the bridge.
  683. */
  684. private function findFocusManagerComponent2(
  685. o:InteractiveObject):DisplayObject
  686. {
  687. try
  688. {
  689. while (o)
  690. {
  691. if ((o is IFocusManagerComponent && IFocusManagerComponent(o).focusEnabled) ||
  692. o is ISWFLoader)
  693. return o;
  694. o = o.parent;
  695. }
  696. }
  697. catch (error:SecurityError)
  698. {
  699. // can happen in a loaded child swf
  700. // trace("findFocusManagerComponent: handling security error");
  701. }
  702. // tab was set somewhere else
  703. return null;
  704. }
  705. /**
  706. * @inheritDoc
  707. */
  708. public function moveFocus(direction:String, fromDisplayObject:DisplayObject = null):void
  709. {
  710. if (direction == FocusRequestDirection.TOP)
  711. {
  712. setFocusToTop();
  713. return;
  714. }
  715. if (direction == FocusRequestDirection.BOTTOM)
  716. {
  717. setFocusToBottom();
  718. return;
  719. }
  720. var keyboardEvent:KeyboardEvent = new KeyboardEvent(KeyboardEvent.KEY_DOWN);
  721. keyboardEvent.keyCode = Keyboard.TAB;
  722. keyboardEvent.shiftKey = (direction == FocusRequestDirection.FORWARD) ? false : true;
  723. fauxFocus = fromDisplayObject;
  724. keyDownHandler(keyboardEvent);
  725. var focusEvent:FocusEvent = new FocusEvent(FocusEvent.KEY_FOCUS_CHANGE);
  726. focusEvent.keyCode = Keyboard.TAB;
  727. focusEvent.shiftKey = (direction == FocusRequestDirection.FORWARD) ? false : true;
  728. keyFocusChangeHandler(focusEvent);
  729. fauxFocus = null;
  730. }
  731. /**
  732. * @private
  733. * Returns true if p is a parent of o.
  734. */
  735. private function isParent(p:DisplayObjectContainer, o:DisplayObject):Boolean
  736. {
  737. if (p is IRawChildrenContainer)
  738. return IRawChildrenContainer(p).rawChildren.contains(o);
  739. return p.contains(o);
  740. }
  741. private function isEnabledAndVisible(o:DisplayObject):Boolean
  742. {
  743. var formParent:DisplayObjectContainer = DisplayObject(form).parent;
  744. while (o != formParent)
  745. {
  746. if (o is IUIComponent)
  747. if (!IUIComponent(o).enabled)
  748. return false;
  749. if (!o.visible)
  750. return false;
  751. o = o.parent;
  752. }
  753. return true;
  754. }
  755. /**
  756. * @private
  757. */
  758. private function sortByTabIndex(a:InteractiveObject, b:InteractiveObject):int
  759. {
  760. var aa:int = a.tabIndex;
  761. var bb:int = b.tabIndex;
  762. if (aa == -1)
  763. aa = int.MAX_VALUE;
  764. if (bb == -1)
  765. bb = int.MAX_VALUE;
  766. return (aa > bb ? 1 :
  767. aa < bb ? -1 : sortByDepth(DisplayObject(a), DisplayObject(b)));
  768. }
  769. /**
  770. * @private
  771. */
  772. private function sortFocusableObjectsTabIndex():void
  773. {
  774. //trace("FocusableObjectsTabIndex");
  775. focusableCandidates = [];
  776. var n:int = focusableObjects.length;
  777. for (var i:int = 0; i < n; i++)
  778. {
  779. var c:IFocusManagerComponent = focusableObjects[i] as IFocusManagerComponent;
  780. if ((c && c.tabIndex && !isNaN(Number(c.tabIndex))) ||
  781. focusableObjects[i] is ISWFLoader)
  782. {
  783. // if we get here, it is a candidate
  784. focusableCandidates.push(focusableObjects[i]);
  785. }
  786. }
  787. focusableCandidates.sort(sortByTabIndex);
  788. }
  789. /**
  790. * @private
  791. */
  792. private function sortByDepth(aa:DisplayObject, bb:DisplayObject):Number
  793. {
  794. var val1:String = "";
  795. var val2:String = "";
  796. var index:int;
  797. var tmp:String;
  798. var tmp2:String;
  799. var zeros:String = "0000";
  800. var a:DisplayObject = DisplayObject(aa);
  801. var b:DisplayObject = DisplayObject(bb);
  802. while (a != DisplayObject(form) && a.parent)
  803. {
  804. index = getChildIndex(a.parent, a);
  805. tmp = index.toString(16);
  806. if (tmp.length < 4)
  807. {
  808. tmp2 = zeros.substring(0, 4 - tmp.length) + tmp;
  809. }
  810. val1 = tmp2 + val1;
  811. a = a.parent;
  812. }
  813. while (b != DisplayObject(form) && b.parent)
  814. {
  815. index = getChildIndex(b.parent, b);
  816. tmp = index.toString(16);
  817. if (tmp.length < 4)
  818. {
  819. tmp2 = zeros.substring(0, 4 - tmp.length) + tmp;
  820. }
  821. val2 = tmp2 + val2;
  822. b = b.parent;
  823. }
  824. return val1 > val2 ? 1 : val1 < val2 ? -1 : 0;
  825. }
  826. private function getChildIndex(parent:DisplayObjectContainer, child:DisplayObject):int
  827. {
  828. try
  829. {
  830. return parent.getChildIndex(child);
  831. }
  832. catch(e:Error)
  833. {
  834. if (parent is IRawChildrenContainer)
  835. return IRawChildrenContainer(parent).rawChildren.getChildIndex(child);
  836. throw e;
  837. }
  838. throw new Error("FocusManager.getChildIndex failed"); // shouldn't ever get here
  839. }
  840. /**
  841. * @private
  842. * Calculate what focusableObjects are valid tab candidates.
  843. */
  844. private function sortFocusableObjects():void
  845. {
  846. // trace("FocusableObjects " + focusableObjects.length.toString());
  847. focusableCandidates = [];
  848. var n:int = focusableObjects.length;
  849. for (var i:int = 0; i < n; i++)
  850. {
  851. var c:InteractiveObject = focusableObjects[i];
  852. // trace(" " + c);
  853. if (c.tabIndex && !isNaN(Number(c.tabIndex)) && c.tabIndex > 0)
  854. {
  855. sortFocusableObjectsTabIndex();
  856. return;
  857. }
  858. focusableCandidates.push(c);
  859. }
  860. focusableCandidates.sort(sortByDepth);
  861. }
  862. /**
  863. * Call this method to make the system
  864. * think the Enter key was pressed and the defaultButton was clicked
  865. */
  866. mx_internal function sendDefaultButtonEvent():void
  867. {
  868. // trace("FocusManager.sendDefaultButtonEvent " + defButton);
  869. defButton.dispatchEvent(new MouseEvent("click"));
  870. }
  871. /**
  872. * @private
  873. * Do a tree walk and add all children you can find.
  874. */
  875. private function addFocusables(o:DisplayObject, skipTopLevel:Boolean = false):void
  876. {
  877. // trace(">>addFocusables " + o);
  878. if ((o is IFocusManagerComponent) && !skipTopLevel)
  879. {
  880. var addToFocusables:Boolean = false;
  881. if (o is IFocusManagerComponent)
  882. {
  883. var focusable:IFocusManagerComponent = IFocusManagerComponent(o);
  884. if (focusable.focusEnabled)
  885. {
  886. if (focusable.tabEnabled && isTabVisible(o))
  887. {
  888. addToFocusables = true;
  889. }
  890. }
  891. }
  892. if (addToFocusables)
  893. {
  894. if (focusableObjects.indexOf(o) == -1)
  895. {
  896. focusableObjects.push(o);
  897. calculateCandidates = true;
  898. // trace("FM added " + o);
  899. }
  900. o.addEventListener("tabEnabledChange", tabEnabledChangeHandler);
  901. o.addEventListener("tabIndexChange", tabIndexChangeHandler);
  902. }
  903. }
  904. if (o is DisplayObjectContainer)
  905. {
  906. var doc:DisplayObjectContainer = DisplayObjectContainer(o);
  907. // Even if they aren't focusable now,
  908. // listen in case they become later.
  909. o.addEventListener("tabChildrenChange", tabChildrenChangeHandler);
  910. if (doc.tabChildren)
  911. {
  912. if (o is IRawChildrenContainer)
  913. {
  914. // trace("using view rawChildren");
  915. var rawChildren:IChildList = IRawChildrenContainer(o).rawChildren;
  916. // recursively visit and add children of components
  917. // we don't do this for containers because we get individual
  918. // adds for the individual children
  919. var i:int;
  920. for (i = 0; i < rawChildren.numChildren; i++)
  921. {
  922. try
  923. {
  924. addFocusables(rawChildren.getChildAt(i));
  925. }
  926. catch(error:SecurityError)
  927. {
  928. // Ignore this child if we can't access it
  929. // trace("addFocusables: ignoring security error getting child from rawChildren: " + error);
  930. }
  931. }
  932. }
  933. else
  934. {
  935. // trace("using container's children");
  936. // recursively visit and add children of components
  937. // we don't do this for containers because we get individual
  938. // adds for the individual children
  939. for (i = 0; i < doc.numChildren; i++)
  940. {
  941. try
  942. {
  943. addFocusables(doc.getChildAt(i));
  944. }
  945. catch(error:SecurityError)
  946. {
  947. // Ignore this child if we can't access it
  948. // trace("addFocusables: ignoring security error getting child at document." + error);
  949. }
  950. }
  951. }
  952. }
  953. }
  954. // trace("<<addFocusables " + o);
  955. }
  956. /**
  957. * @private
  958. * is it really tabbable?
  959. */
  960. private function isTabVisible(o:DisplayObject):Boolean
  961. {
  962. var s:DisplayObject = DisplayObject(form.systemManager);
  963. if (!s) return false;
  964. var p:DisplayObjectContainer = o.parent;
  965. while (p && p != s)
  966. {
  967. if (!p.tabChildren)
  968. return false;
  969. p = p.parent;
  970. }
  971. return true;
  972. }
  973. private function isValidFocusCandidate(o:DisplayObject, g:String):Boolean
  974. {
  975. if (!isEnabledAndVisible(o))
  976. return false;
  977. if (o is IFocusManagerGroup)
  978. {
  979. // reject if it is in the same tabgroup
  980. var tg:IFocusManagerGroup = IFocusManagerGroup(o);
  981. if (g == tg.groupName) return false;
  982. }
  983. return true;
  984. }
  985. private function getIndexOfFocusedObject(o:DisplayObject):int
  986. {
  987. if (!o)
  988. return -1;
  989. var n:int = focusableCandidates.length;
  990. // trace(" focusableCandidates " + n);
  991. var i:int = 0;
  992. for (i = 0; i < n; i++)
  993. {
  994. // trace(" comparing " + focusableCandidates[i]);
  995. if (focusableCandidates[i] == o)
  996. return i;
  997. }
  998. // no match? try again with a slower match for certain
  999. // cases like DG editors
  1000. for (i = 0; i < n; i++)
  1001. {
  1002. var iui:IUIComponent = focusableCandidates[i] as IUIComponent;
  1003. if (iui && iui.owns(o))
  1004. return i;
  1005. }
  1006. return -1;
  1007. }
  1008. private function getIndexOfNextObject(i:int, shiftKey:Boolean, bSearchAll:Boolean, groupName:String):int
  1009. {
  1010. var n:int = focusableCandidates.length;
  1011. var start:int = i;
  1012. while (true)
  1013. {
  1014. if (shiftKey)
  1015. i--;
  1016. else
  1017. i++;
  1018. if (bSearchAll)
  1019. {
  1020. if (shiftKey && i < 0)
  1021. break;
  1022. if (!shiftKey && i == n)
  1023. break;
  1024. }
  1025. else
  1026. {
  1027. i = (i + n) % n;
  1028. // came around and found the original
  1029. if (start == i)
  1030. break;
  1031. }
  1032. // trace("testing " + focusableCandidates[i]);
  1033. if (isValidFocusCandidate(focusableCandidates[i], groupName))
  1034. {
  1035. // trace(" stopped at " + i);
  1036. var o:DisplayObject = DisplayObject(findFocusManagerComponent2(focusableCandidates[i]));
  1037. if (o is IFocusManagerGroup)
  1038. {
  1039. // look around to see if there's a selected member in the tabgroup
  1040. // otherwise use the first one we found.
  1041. var tg1:IFocusManagerGroup = IFocusManagerGroup(o);
  1042. for (var j:int = 0; j < focusableCandidates.length; j++)
  1043. {
  1044. var obj:DisplayObject = focusableCandidates[j];
  1045. if (obj is IFocusManagerGroup)
  1046. {
  1047. var tg2:IFocusManagerGroup = IFocusManagerGroup(obj);
  1048. if (tg2.groupName == tg1.groupName && tg2.selected)
  1049. {
  1050. // if objects of same group have different tab index
  1051. // skip you aren't selected.
  1052. if (InteractiveObject(obj).tabIndex != InteractiveObject(o).tabIndex && !tg1.selected)
  1053. return getIndexOfNextObject(i, shiftKey, bSearchAll, groupName);
  1054. i = j;
  1055. break;
  1056. }
  1057. }
  1058. }
  1059. }
  1060. return i;
  1061. }
  1062. }
  1063. return i;
  1064. }
  1065. /**
  1066. * @private
  1067. */
  1068. private function setFocusToNextObject(event:FocusEvent):void
  1069. {
  1070. focusChanged = false;
  1071. if (focusableObjects.length == 0)
  1072. return;
  1073. var focusInfo:FocusInfo = getNextFocusManagerComponent2(event.shiftKey, fauxFocus);
  1074. // trace("winner = ", o);
  1075. // If we are about to wrap focus around, send focus back to the parent.
  1076. if (!popup && focusInfo.wrapped)
  1077. {
  1078. if (getParentBridge())
  1079. {
  1080. moveFocusToParent(event.shiftKey);
  1081. return;
  1082. }
  1083. }
  1084. setFocusToComponent(focusInfo.displayObject, event.shiftKey);
  1085. }
  1086. private function setFocusToComponent(o:Object, shiftKey:Boolean):void
  1087. {
  1088. focusChanged = false;
  1089. if (o)
  1090. {
  1091. if (o is ISWFLoader && ISWFLoader(o).swfBridge)
  1092. {
  1093. // send message to child swf to move focus.
  1094. // trace("pass focus from " + this.form.systemManager.loaderInfo.url + " to " + DisplayObject(o).loaderInfo.url);
  1095. var request:SWFBridgeRequest = new SWFBridgeRequest(SWFBridgeRequest.MOVE_FOCUS_REQUEST,
  1096. false, true, null,
  1097. shiftKey ? FocusRequestDirection.BOTTOM :
  1098. FocusRequestDirection.TOP);
  1099. var sandboxBridge:IEventDispatcher = ISWFLoader(o).swfBridge;
  1100. if (sandboxBridge)
  1101. {
  1102. sandboxBridge.dispatchEvent(request);
  1103. focusChanged = request.data;
  1104. }
  1105. }
  1106. else if (o is IFocusManagerComplexComponent)
  1107. {
  1108. IFocusManagerComplexComponent(o).assignFocus(shiftKey ? "bottom" : "top");
  1109. focusChanged = true;
  1110. }
  1111. else if (o is IFocusManagerComponent)
  1112. {
  1113. setFocus(IFocusManagerComponent(o));
  1114. focusChanged = true;
  1115. }
  1116. }
  1117. }
  1118. /**
  1119. * @private
  1120. */
  1121. private function setFocusToTop():void
  1122. {
  1123. setFocusToNextIndex(-1, false);
  1124. }
  1125. /**
  1126. * @private
  1127. */
  1128. private function setFocusToBottom():void
  1129. {
  1130. setFocusToNextIndex(focusableObjects.length, true);
  1131. }
  1132. /**
  1133. * @private
  1134. */
  1135. private function setFocusToNextIndex(index:int, shiftKey:Boolean):void
  1136. {
  1137. if (focusableObjects.length == 0)
  1138. return;
  1139. // I think we'll have time to do this here instead of at creation time
  1140. // this makes and orders the focusableCandidates array
  1141. if (calculateCandidates)
  1142. {
  1143. sortFocusableObjects();
  1144. calculateCandidates = false;
  1145. }
  1146. var focusInfo:FocusInfo = getNextFocusManagerComponent2(shiftKey, null, index);
  1147. // If we are about to wrap focus around, send focus back to the parent.
  1148. if (!popup && focusInfo.wrapped)
  1149. {
  1150. if (getParentBridge())
  1151. {
  1152. moveFocusToParent(shiftKey);
  1153. return;
  1154. }
  1155. }
  1156. setFocusToComponent(focusInfo.displayObject, shiftKey);
  1157. }
  1158. /**
  1159. * @inheritDoc
  1160. */
  1161. public function getNextFocusManagerComponent(
  1162. backward:Boolean = false):IFocusManagerComponent
  1163. {
  1164. return getNextFocusManagerComponent2(false, fauxFocus).displayObject as IFocusManagerComponent;
  1165. }
  1166. /**
  1167. * Find the next object to set focus to.
  1168. *
  1169. * @param backward true if moving in the backwards in the tab order, false if moving forward.
  1170. * @param fromObject object to move focus from, if null move from the current focus.
  1171. * @param formIndex index to move focus from, if specified use fromIndex to find the
  1172. * object, not fromObject.
  1173. */
  1174. private function getNextFocusManagerComponent2(
  1175. backward:Boolean = false,
  1176. fromObject:DisplayObject = null,
  1177. fromIndex:int = FROM_INDEX_UNSPECIFIED):FocusInfo
  1178. {
  1179. if (focusableObjects.length == 0)
  1180. return null;
  1181. // I think we'll have time to do this here instead of at creation time
  1182. // this makes and orders the focusableCandidates array
  1183. if (calculateCandidates)
  1184. {
  1185. sortFocusableObjects();
  1186. calculateCandidates = false;
  1187. }
  1188. // trace("focus was at " + o);
  1189. // trace("focusableObjects " + focusableObjects.length);
  1190. var i:int = fromIndex;
  1191. if (fromIndex == FROM_INDEX_UNSPECIFIED)
  1192. {
  1193. // if there is no passed in object, then get the object that has the focus
  1194. var o:DisplayObject = fromObject;
  1195. if (!o)
  1196. o = form.systemManager.stage.focus;
  1197. o = DisplayObject(findFocusManagerComponent2(InteractiveObject(o)));
  1198. var g:String = "";
  1199. if (o is IFocusManagerGroup)
  1200. {
  1201. var tg:IFocusManagerGroup = IFocusManagerGroup(o);
  1202. g = tg.groupName;
  1203. }
  1204. i = getIndexOfFocusedObject(o);
  1205. }
  1206. // trace(" starting at " + i);
  1207. var bSearchAll:Boolean = false;
  1208. var start:int = i;
  1209. if (i == -1) // we didn't find it
  1210. {
  1211. if (backward)
  1212. i = focusableCandidates.length;
  1213. bSearchAll = true;
  1214. // trace("search all " + i);
  1215. }
  1216. var j:int = getIndexOfNextObject(i, backward, bSearchAll, g);
  1217. // if we wrapped around, get if we have a parent we should pass
  1218. // focus to.
  1219. var wrapped:Boolean = false;
  1220. if (backward)
  1221. {
  1222. if (j >= i)
  1223. wrapped = true;
  1224. }
  1225. else if (j <= i)
  1226. wrapped = true;
  1227. var focusInfo:FocusInfo = new FocusInfo();
  1228. focusInfo.displayObject = findFocusManagerComponent2(focusableCandidates[j]);
  1229. focusInfo.wrapped = wrapped;
  1230. return focusInfo;
  1231. }
  1232. /**
  1233. * @private
  1234. */
  1235. private function getTopLevelFocusTarget(o:InteractiveObject):InteractiveObject
  1236. {
  1237. while (o != InteractiveObject(form))
  1238. {
  1239. if (o is IFocusManagerComponent &&
  1240. IFocusManagerComponent(o).focusEnabled &&
  1241. IFocusManagerComponent(o).mouseFocusEnabled &&
  1242. (o is IUIComponent ? IUIComponent(o).enabled : true))
  1243. return o;
  1244. // if we cross a boundry into a bridged application, then return null so
  1245. // the target is only processed at the lowest level
  1246. if (o.parent is ISWFLoader)
  1247. {
  1248. if (ISWFLoader(o.parent).swfBridge)
  1249. return null;
  1250. }
  1251. o = o.parent;
  1252. if (o == null)
  1253. break;
  1254. }
  1255. return null;
  1256. }
  1257. /**
  1258. * Returns a String representation of the component hosting the FocusManager object,
  1259. * with the String <code>".focusManager"</code> appended to the end of the String.
  1260. *
  1261. * @return Returns a String representation of the component hosting the FocusManager object,
  1262. * with the String <code>".focusManager"</code> appended to the end of the String.
  1263. */
  1264. public function toString():String
  1265. {
  1266. return Object(form).toString() + ".focusManager";
  1267. }
  1268. //--------------------------------------------------------------------------
  1269. //
  1270. // Event handlers
  1271. //
  1272. //--------------------------------------------------------------------------
  1273. /**
  1274. * @private
  1275. * Listen for children being added
  1276. * and see if they are focus candidates.
  1277. */
  1278. private function addedHandler(event:Event):void
  1279. {
  1280. var target:DisplayObject = DisplayObject(event.target);
  1281. // trace("FM: addedHandler: got added for " + target);
  1282. // if it is truly parented, add it, otherwise it will get added when the top of the tree
  1283. // gets parented.
  1284. if (target.stage)
  1285. {
  1286. // trace("FM: addedHandler: adding focusables");
  1287. addFocusables(DisplayObject(event.target));
  1288. }
  1289. }
  1290. /**
  1291. * @private
  1292. * Listen for children being removed.
  1293. */
  1294. private function removedHandler(event:Event):void
  1295. {
  1296. var i:int;
  1297. var o:DisplayObject = DisplayObject(event.target);
  1298. // trace("FM got added for " + event.target);
  1299. if (o is IFocusManagerComponent)
  1300. {
  1301. for (i = 0; i < focusableObjects.length; i++)
  1302. {
  1303. if (o == focusableObjects[i])
  1304. {
  1305. if (o == _lastFocus)
  1306. {
  1307. _lastFocus.drawFocus(false);
  1308. _lastFocus = null;
  1309. }
  1310. // trace("FM removed " + o);
  1311. o.removeEventListener("tabEnabledChange", tabEnabledChangeHandler);
  1312. o.removeEventListener("tabIndexChange", tabIndexChangeHandler);
  1313. focusableObjects.splice(i, 1);
  1314. focusableCandidates = [];
  1315. calculateCandidates = true;
  1316. break;
  1317. }
  1318. }
  1319. }
  1320. removeFocusables(o, false);
  1321. }
  1322. /**
  1323. * After the form is added to the stage, if there are no focusable objects,
  1324. * add the form and its children to the list of focuable objects because
  1325. * this application may have been loaded before the
  1326. * top-level system manager was added to the stage.
  1327. */
  1328. private function addedToStageHandler(event:Event):void
  1329. {
  1330. _form.removeEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
  1331. if (focusableObjects.length == 0)
  1332. {
  1333. addFocusables(DisplayObject(_form));
  1334. calculateCandidates = true;
  1335. }
  1336. }
  1337. /**
  1338. * @private
  1339. */
  1340. private function removeFocusables(o:DisplayObject, dontRemoveTabChildrenHandler:Boolean):void
  1341. {
  1342. var i:int;
  1343. if (o is DisplayObjectContainer)
  1344. {
  1345. if (!dontRemoveTabChildrenHandler)
  1346. o.removeEventListener("tabChildrenChange", tabChildrenChangeHandler);
  1347. for (i = 0; i < focusableObjects.length; i++)
  1348. {
  1349. if (isParent(DisplayObjectContainer(o), focusableObjects[i]))
  1350. {
  1351. if (focusableObjects[i] == _lastFocus)
  1352. {
  1353. _lastFocus.drawFocus(false);
  1354. _lastFocus = null;
  1355. }
  1356. // trace("FM removed " + focusableObjects[i]);
  1357. focusableObjects[i].removeEventListener(
  1358. "tabEnabledChange", tabEnabledChangeHandler);
  1359. focusableObjects[i].removeEventListener(
  1360. "tabIndexChange", tabIndexChangeHandler);
  1361. focusableObjects.splice(i, 1);
  1362. i = i - 1; // because increment would skip one
  1363. focusableCandidates = [];
  1364. calculateCandidates = true;
  1365. }
  1366. }
  1367. }
  1368. }
  1369. /**
  1370. * @private
  1371. */
  1372. private function showHandler(event:Event):void
  1373. {
  1374. form.systemManager.activate(form);
  1375. }
  1376. /**
  1377. * @private
  1378. */
  1379. private function hideHandler(event:Event):void
  1380. {
  1381. form.systemManager.deactivate(form);
  1382. }
  1383. /**
  1384. * @private
  1385. */
  1386. private function creationCompleteHandler(event:FlexEvent):void
  1387. {
  1388. var o:DisplayObject = DisplayObject(form);
  1389. if (o.parent && o.visible && !activated)
  1390. form.systemManager.activate(form);
  1391. }
  1392. /**
  1393. * @private
  1394. * Add or remove if tabbing properties change.
  1395. */
  1396. private function tabIndexChangeHandler(event:Event):void
  1397. {
  1398. calculateCandidates = true;
  1399. }
  1400. /**
  1401. * @private
  1402. * Add or remove if tabbing properties change.
  1403. */
  1404. private function

Large files files are truncated, but you can click here to view the full file