I recently had a bit of a challenge to tackle with our Workspace application and thought I would share some details. As many of you probably know from trying out the application, Workspace is meant to be kept open to fully capitalize on it's collaborative features. The application provides a lot of behavior that is based on real-time communication, such as content being updated or users being added to Spaces. All of this works quite well right now, and we are already working on more features as well as some simplification of the interface to allow new users to get up and running more quickly.
We have, however, noticed a small but annoying glitch that happens as a result of certain real-time notifications that trigger Flex Alerts. Namely, if the application is minimized and an Alert is triggered, when the application is maximized, the Alert does not appear in the proper place. Normally, an Alert will automatically center itself in the window where it appears. But if the application is minimized, this centering does not happen. So when the app is maximized again, the modal Alert is located far in the upper left corner of the screen, with most of it's content off the screen completely. Users had a hard time figuring out what was happening, and since the Alert is modal, the app can't be used until the Alert is closed. This resulted in a lot of confused users!
I set out to solve this issue by triggering a re-centering of any open Alerts when the application is resized, but this turned out to be more difficult than it first appears. At first, this seemed like it should be fairly simple: the Flex SystemManager object contains a property called popUpChildren, which references any PopUp objects that are open. So no problem, right? Just loop over this list and recenter them.
In a frustrating turn of events, Flex Alert objects are not stored in this list. I'm not sure why, but they aren't. This seems like an oversight or bug, but the fact remains that looking at the popUpChildren wouldn't work. This list appears to only contain any PopUp instances created using the PopUpManager, but not any Alert instances. Nor is there a similar list such as alertChildren. It turns out that Alerts are added to the SystemManager's display list but are not actually kept track of anywhere.
The first part of the solution was to add an application resize event handler that loops through all children of the SystemManager's display list and locates any that are instances of the Alert class:
var systemManager : SystemManager = Application.application.systemManager;
// Look for children of SystemManager that are Alerts, and recenter them.
for ( var i:int = 0; i < systemManager.numChildren; i++ )
{
var thisChild : Object = systemManager.getChildAt( i );
if( thisChild is Alert )
{
PopUpManager.centerPopUp( thisChild as IFlexDisplayObject );
}
}
This code actually does work and will recenter the Alert. But in another frustrating turn (and what certainly appears to be another bug), the re-centered Alerts did not display correctly. Any text within the Alert box that was "off the screen" prior to re-centering would not display. I tried triggering an invalidateDisplayList() and invalidateProperties(), but nothing would get the Alert to re-draw the text correctly. I was banging my head against the monitor when my astute colleague Joe Rinehart made a suggestion that turned out to give the desired result:
var systemManager : SystemManager = Application.application.systemManager;
// Look for children of SystemManager that are Alerts, and recenter them.
for ( var i:int = 0; i < systemManager.numChildren; i++ )
{
var thisChild : Object = systemManager.getChildAt( i );
if( thisChild is Alert )
{
PopUpManager.removePopUp( thisChild as IFlexDisplayObject );
PopUpManager.addPopUp( thisChild as IFlexDisplayObject, this );
PopUpManager.centerPopUp( thisChild as IFlexDisplayObject );
}
}
Essentially, you have to kick Flex in the head by removing the Alert, re-adding it, and then re-centering it for good measure. All of this seems like a lot of hoops to jump through to accomplish something that seems like it should be rather easy to do, but there you have it. Going forward, we'll probably set up some sort of centralized manager class that can be used to create and keep track of both Alerts, PopUps, and any other components that need to display at the very top display list of the application (such as Callouts and Tooltips), and we're also looking at some Growl-like notifications to minimize the use of Alerts. But that's a topic for another day (probably in the very near future though). In any event, hopefully this post will help anyone who ends up in a similar situation!