PageRenderTime 202ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/frameworks/projects/framework/src/mx/managers/systemClasses/ActiveWindowManager.as

https://github.com/bigbangtechnology/flex
ActionScript | 514 lines | 293 code | 70 blank | 151 comment | 83 complexity | dd74c5461be68bd88d957053c6653429 MD5 | raw 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.systemClasses
  12. {
  13. import flash.display.DisplayObject;
  14. import flash.display.InteractiveObject;
  15. import flash.display.Sprite;
  16. import flash.events.Event;
  17. import flash.events.EventDispatcher;
  18. import flash.events.IEventDispatcher;
  19. import flash.events.FocusEvent;
  20. import flash.events.MouseEvent;
  21. import mx.core.IChildList;
  22. import mx.core.IFlexModuleFactory;
  23. import mx.core.IRawChildrenContainer;
  24. import mx.core.IUIComponent;
  25. import mx.core.mx_internal;
  26. import mx.core.Singleton;
  27. import mx.events.DynamicEvent;
  28. import mx.events.Request;
  29. import mx.managers.IActiveWindowManager;
  30. import mx.managers.IFocusManagerContainer;
  31. import mx.managers.ISystemManager;
  32. use namespace mx_internal;
  33. [ExcludeClass]
  34. [Mixin]
  35. public class ActiveWindowManager extends EventDispatcher implements IActiveWindowManager
  36. {
  37. include "../../core/Version.as";
  38. //--------------------------------------------------------------------------
  39. //
  40. // Class Method
  41. //
  42. //--------------------------------------------------------------------------
  43. public static function init(fbs:IFlexModuleFactory):void
  44. {
  45. Singleton.registerClass("mx.managers::IActiveWindowManager", ActiveWindowManager);
  46. }
  47. //--------------------------------------------------------------------------
  48. //
  49. // Constructor
  50. //
  51. //--------------------------------------------------------------------------
  52. /**
  53. * Constructor.
  54. *
  55. * <p>This is the starting point for all Flex applications.
  56. * This class is set to be the root class of a Flex SWF file.
  57. * Flash Player instantiates an instance of this class,
  58. * causing this constructor to be called.</p>
  59. */
  60. public function ActiveWindowManager(systemManager:ISystemManager = null)
  61. {
  62. super();
  63. if (!systemManager)
  64. return;
  65. this.systemManager = systemManager;
  66. // capture mouse down so we can switch top level windows and activate
  67. // the right focus manager before the components inside start
  68. // processing the event
  69. if (systemManager.isTopLevelRoot() || systemManager.getSandboxRoot() == systemManager)
  70. systemManager.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler, true);
  71. }
  72. //--------------------------------------------------------------------------
  73. //
  74. // Variables
  75. //
  76. //--------------------------------------------------------------------------
  77. /**
  78. * @private
  79. */
  80. private var systemManager:ISystemManager;
  81. /**
  82. * @private
  83. * List of top level windows.
  84. */
  85. mx_internal var forms:Array = [];
  86. /**
  87. * @private
  88. * The current top level window.
  89. *
  90. * Will be of type IFocusManagerContainer if the form
  91. * in the top-level system manager's application domain
  92. * or a child of that application domain. Otherwise the
  93. * form will be of type RemotePopUp.
  94. */
  95. mx_internal var form:Object;
  96. //----------------------------------
  97. // numModalWindows
  98. //----------------------------------
  99. /**
  100. * @private
  101. * Storage for the numModalWindows property.
  102. */
  103. private var _numModalWindows:int = 0;
  104. /**
  105. * The number of modal windows. Modal windows don't allow
  106. * clicking in another windows which would normally
  107. * activate the FocusManager in that window. The PopUpManager
  108. * modifies this count as it creates and destroys modal windows.
  109. */
  110. public function get numModalWindows():int
  111. {
  112. return _numModalWindows;
  113. }
  114. /**
  115. * @private
  116. */
  117. public function set numModalWindows(value:int):void
  118. {
  119. _numModalWindows = value;
  120. systemManager.numModalWindows = value;
  121. }
  122. //--------------------------------------------------------------------------
  123. //
  124. // Methods: Focus
  125. //
  126. //--------------------------------------------------------------------------
  127. /**
  128. * @inheritDoc
  129. */
  130. public function activate(f:Object):void
  131. {
  132. activateForm(f);
  133. }
  134. /**
  135. * @private
  136. *
  137. * New version of activate that does not require a
  138. * IFocusManagerContainer.
  139. */
  140. private function activateForm(f:Object):void
  141. {
  142. var e:DynamicEvent;
  143. // trace("SM: activate " + f + " " + forms.length);
  144. if (form)
  145. {
  146. if (form != f && forms.length > 1)
  147. {
  148. if (hasEventListener("activateForm"))
  149. {
  150. e = new DynamicEvent("activateForm", false, true);
  151. e.form = f;
  152. }
  153. // Switch the active form.
  154. if (!e || dispatchEvent(e))
  155. {
  156. var z:IFocusManagerContainer = IFocusManagerContainer(form);
  157. // trace("OLW " + f + " deactivating old form " + z);
  158. z.focusManager.deactivate();
  159. }
  160. }
  161. }
  162. form = f;
  163. var e2:DynamicEvent;
  164. if (hasEventListener("activatedForm"))
  165. {
  166. e2 = new DynamicEvent("activatedForm", false, true);
  167. e2.form = f;
  168. }
  169. if (!e2 || dispatchEvent(e2))
  170. {
  171. if (f.focusManager)
  172. {
  173. // trace("has focus manager");
  174. f.focusManager.activate();
  175. }
  176. }
  177. // trace("END SM: activate " + f);
  178. }
  179. /**
  180. * @inheritDoc
  181. */
  182. public function deactivate(f:Object):void
  183. {
  184. deactivateForm(Object(f));
  185. }
  186. /**
  187. * @private
  188. *
  189. * New version of deactivate that works with remote pop ups.
  190. *
  191. */
  192. private function deactivateForm(f:Object):void
  193. {
  194. var e:DynamicEvent;
  195. // trace(">>SM: deactivate " + f);
  196. if (form)
  197. {
  198. // If there's more than one form and this is it, find a new form.
  199. if (form == f && forms.length > 1)
  200. {
  201. if (hasEventListener("deactivateForm"))
  202. {
  203. e = new DynamicEvent("deactivateForm", false, true);
  204. e.form = form;
  205. }
  206. if (!e || dispatchEvent(e))
  207. form.focusManager.deactivate();
  208. form = findLastActiveForm(f);
  209. var e2:DynamicEvent;
  210. // make sure we have a valid top level window.
  211. // This can be null if top level window has been hidden for some reason.
  212. if (form)
  213. {
  214. if (hasEventListener("deactivatedForm"))
  215. {
  216. e2 = new DynamicEvent("deactivatedForm", false, true);
  217. e2.form = form;
  218. }
  219. if (!e2 || dispatchEvent(e2))
  220. {
  221. // make sure we have a valid top level window.
  222. // This can be null if top level window has been hidden for some reason.
  223. if (form)
  224. {
  225. form.focusManager.activate();
  226. }
  227. }
  228. }
  229. }
  230. }
  231. // trace("<<SM: deactivate " + f);
  232. }
  233. /**
  234. * @private
  235. *
  236. * @param f form being deactivated
  237. *
  238. * @return the next form to activate, excluding the form being deactivated.
  239. */
  240. private function findLastActiveForm(f:Object):Object
  241. {
  242. var n:int = forms.length;
  243. for (var i:int = forms.length - 1; i >= 0; i--)
  244. {
  245. // Verify the form is visible and enabled
  246. if (forms[i] != f && canActivatePopUp(forms[i]))
  247. return forms[i];
  248. }
  249. return null; // should never get here
  250. }
  251. /**
  252. * @private
  253. *
  254. * @return true if the form can be activated, false otherwise.
  255. */
  256. private function canActivatePopUp(f:Object):Boolean
  257. {
  258. var e:Request;
  259. if (hasEventListener("canActivateForm"))
  260. {
  261. e = new Request("canActivateForm", false, true);
  262. e.value = f;
  263. if (!dispatchEvent(e))
  264. {
  265. return e.value;
  266. }
  267. }
  268. if (canActivateLocalComponent(f))
  269. return true;
  270. return false;
  271. }
  272. /**
  273. * @private
  274. *
  275. * Test is a local component can be activated.
  276. */
  277. private function canActivateLocalComponent(o:Object):Boolean
  278. {
  279. if (o is Sprite && o is IUIComponent &&
  280. Sprite(o).visible && IUIComponent(o).enabled)
  281. return true;
  282. return false;
  283. }
  284. /**
  285. * @inheritDoc
  286. */
  287. public function addFocusManager(f:IFocusManagerContainer):void
  288. {
  289. // trace("OLW: add focus manager" + f);
  290. forms.push(f);
  291. // trace("END OLW: add focus manager" + f);
  292. }
  293. /**
  294. * @inheritDoc
  295. */
  296. public function removeFocusManager(f:IFocusManagerContainer):void
  297. {
  298. // trace("OLW: remove focus manager" + f);
  299. var n:int = forms.length;
  300. for (var i:int = 0; i < n; i++)
  301. {
  302. if (forms[i] == f)
  303. {
  304. if (form == f)
  305. deactivate(f);
  306. // If this is a bridged application, send a message to the parent
  307. // to let them know the form has been deactivated so they can
  308. // activate a new form.
  309. if (hasEventListener("removeFocusManager"))
  310. dispatchEvent(new FocusEvent("removeFocusManager", false, false, InteractiveObject(f)));
  311. forms.splice(i, 1);
  312. // trace("END OLW: successful remove focus manager" + f);
  313. return;
  314. }
  315. }
  316. // trace("END OLW: remove focus manager" + f);
  317. }
  318. /**
  319. * @private
  320. * Track mouse clicks to see if we change top-level forms.
  321. */
  322. private function mouseDownHandler(event:MouseEvent):void
  323. {
  324. // trace("SM:mouseDownHandler " + this);
  325. if (hasEventListener(MouseEvent.MOUSE_DOWN))
  326. if (!dispatchEvent(new FocusEvent(MouseEvent.MOUSE_DOWN, false, true, InteractiveObject(event.target))))
  327. return;
  328. if (numModalWindows == 0) // no modal windows are up
  329. {
  330. if (!systemManager.isTopLevelRoot() || forms.length > 1)
  331. {
  332. var n:int = forms.length;
  333. var p:DisplayObject = DisplayObject(event.target);
  334. var isApplication:Boolean = systemManager.document is IRawChildrenContainer ?
  335. IRawChildrenContainer(systemManager.document).rawChildren.contains(p) :
  336. systemManager.document.contains(p);
  337. while (p)
  338. {
  339. for (var i:int = 0; i < n; i++)
  340. {
  341. var form_i:Object = forms[i];
  342. if (hasEventListener("actualForm"))
  343. {
  344. var request:Request = new Request("actualForm", false, true);
  345. request.value = forms[i];
  346. if (!dispatchEvent(request))
  347. form_i = forms[i].window;
  348. }
  349. if (form_i == p)
  350. {
  351. var j:int = 0;
  352. var index:int;
  353. var newIndex:int;
  354. var childList:IChildList;
  355. if (((p != form) && p is IFocusManagerContainer) ||
  356. (!systemManager.isTopLevelRoot() && p == form))
  357. {
  358. if (systemManager.isTopLevelRoot())
  359. activate(IFocusManagerContainer(p));
  360. if (p == systemManager.document)
  361. {
  362. if (hasEventListener("activateApplication"))
  363. dispatchEvent(new Event("activateApplication"));
  364. }
  365. else if (p is DisplayObject)
  366. {
  367. if (hasEventListener("activateWindow"))
  368. dispatchEvent(new FocusEvent("activateWindow", false, false, InteractiveObject(p)));
  369. }
  370. }
  371. if (systemManager.popUpChildren.contains(p))
  372. childList = systemManager.popUpChildren;
  373. else
  374. childList = systemManager;
  375. index = childList.getChildIndex(p);
  376. newIndex = index;
  377. //we need to reset n because activating p's
  378. //FocusManager could have caused
  379. //forms.length to have changed.
  380. n = forms.length;
  381. for (j = 0; j < n; j++)
  382. {
  383. var f:DisplayObject;
  384. isRemotePopUp = false;
  385. if (hasEventListener("isRemote"))
  386. {
  387. request = new Request("isRemote", false, true);
  388. request.value = forms[j];
  389. var isRemotePopUp:Boolean = false;
  390. if (!dispatchEvent(request))
  391. isRemotePopUp = request.value as Boolean;
  392. }
  393. if (isRemotePopUp)
  394. {
  395. if (forms[j].window is String)
  396. continue;
  397. f = forms[j].window;
  398. }
  399. else
  400. f = forms[j];
  401. if (isRemotePopUp)
  402. {
  403. var fChildIndex:int = getChildListIndex(childList, f);
  404. if (fChildIndex > index)
  405. newIndex = Math.max(fChildIndex, newIndex);
  406. }
  407. else if (childList.contains(f))
  408. if (childList.getChildIndex(f) > index)
  409. newIndex = Math.max(childList.getChildIndex(f), newIndex);
  410. }
  411. if (newIndex > index && !isApplication)
  412. childList.setChildIndex(p, newIndex);
  413. return;
  414. }
  415. }
  416. p = p.parent;
  417. }
  418. }
  419. else if (hasEventListener("activateApplication"))
  420. dispatchEvent(new Event("activateApplication"));
  421. }
  422. }
  423. /**
  424. * @private
  425. *
  426. * Get the index of an object in a given child list.
  427. *
  428. * @return index of f in childList, -1 if f is not in childList.
  429. */
  430. private static function getChildListIndex(childList:IChildList, f:Object):int
  431. {
  432. var index:int = -1;
  433. try
  434. {
  435. index = childList.getChildIndex(DisplayObject(f));
  436. }
  437. catch (e:ArgumentError)
  438. {
  439. // index has been preset to -1 so just continue.
  440. }
  441. return index;
  442. }
  443. }
  444. }