I\'m trying to detect when pop ups are visible (including tool tips if possible). The reason is that I need to hide or freeze (capture a snapshot) the Stage* components (StageWe
There's no really easy way to achieve this. What you can do is this:
Create a custom PopupManager
We create a custom PopupManager class to which we can add some custom functionality. In your case it might for instance be interesting to dispatch an event on the Application, so that we can listen to it from everywhere on the displayList. We'll be extending PopUpManagerImpl which is the default implementation used by Flex.
public class MyPopupManager extends PopUpManagerImpl {
private static var instance:IPopUpManager;
static public function getInstance():IPopUpManager
{
if (!instance) instance = new MyPopupManager();
return instance;
}
override public function addPopUp(
window:IFlexDisplayObject,
parent:DisplayObject,
modal:Boolean=false,
childList:String=null,
moduleFactory:IFlexModuleFactory=null):void
{
super.addPopUp(window, parent, modal, childList, moduleFactory);
var app:IEventDispatcher =
IEventDispatcher(FlexGlobals.topLevelApplication);
app.dispatchEvent(new Event("popupAdded", true));
}
}
We override the addPopup method to dispatch a bubbling event whenever a popup is shown. Ignore the getInstance() method for now. I'll get back to that later. What you do need to know is that FlashBuilder will not automanage some of your imports because these classes were marked as hidden. Nothing to worry about but you'll have to write the import statements manually for:
import mx.managers.IPopUpManager;
import mx.managers.PopUpManagerImpl;
Tell Flex to use your class instead of the default implementation
This would be fairly easy:
import mx.core.Singleton;
Singleton.registerClass("mx.managers::IPopUpManager", MyPopupManager);
The only problem is that Flex has already registered an implementation and you can't override it, even if you execute this on 'preinitialize'. So we'll have to do it before Flex starts bootstrapping. We'll use a custom preloader for that:
public class RegisteringPreloader extends DownloadProgressBar {
override public function initialize():void {
super.initialize();
Singleton.registerClass("mx.managers::IPopUpManager", MyPopupManager);
}
}
DownloadProgressBar is the default Flex preloader. We just add the extra registering code. Now don't forget to tell your application to use this preloader:
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
preloader="RegisteringPreloader" >
Now just listen for the event
addEventListener("popupAdded", onPopupAdded);
PopUpManager.addPopUp(new Panel(), this);
Extra info
Now why does MyPopupManager have to have a static getInstance() method? Well that's because that Singleton class we used to register our implementation, expects every class it registers to be a singleton and hence to have a method called 'getInstance'. It will try to call this method and will crash if it doesn't exist. If you don't know what a singleton is, just google. You'll find tons of information.
PS: I actually learnt something new trying to solve this question (thanks for that).
For my Spark
Application
I had to make a few other modifications to RIAStar's answer. My custom class was not found in the preloader.initialize()
yet ( ApplicationDomain.currentDomain.getDefinition()
) so I added an event listener for the PRELOADER_DOC_FRAME_READY
event.
package com.mydomain.preloaders {
import flash.display.Sprite;
import flash.events.Event;
import flash.system.ApplicationDomain;
import flash.utils.getDefinitionByName;
import mx.core.Singleton;
import mx.events.FlexEvent;
import mx.preloaders.SparkDownloadProgressBar;
public class RegisteringPreloader extends SparkDownloadProgressBar {
public function RegisteringPreloader() {
}
public var preloaderSprite:Sprite;
override public function set preloader(value:Sprite):void {
super.preloader = value;
preloaderSprite = value;
value.addEventListener(FlexEvent.PRELOADER_DOC_FRAME_READY, preloaderCompleteHandler);
}
protected function preloaderCompleteHandler(event:Event):void {
var myCustomClass:Class;
var classPath:String;
var hasDefinition:Boolean;
preloaderSprite.addEventListener(FlexEvent.PRELOADER_DOC_FRAME_READY, preloaderCompleteHandler);
classPath = "com.domain.managers::MyClassImpl";
hasDefinition = ApplicationDomain.currentDomain.hasDefinition(classPath);
if (hasDefinition) {
myCustomClass = Class(getDefinitionByName(classPath));
Singleton.registerClass("mx.managers::ISingletonClass", myCustomClass);
}
}
}
}
The rest of the steps are the same as RIAStar's.