Getting all the popups in a Flex application

Flex Published on December 19, 2009 by Andrea Bresolin Add comments
Live demoSource code (LICENSE)

In Flex, you can create popups easily, but what if you want to get all of them after they’ve already been created? You could keep track of every created popup using a customized function that puts every single instance in an array for example, but what if you’re using a Flex component that simply creates popups in its own way and you cannot keep track of what it creates? Here I’m going to provide a possible solution.

After some debugging, I found out that Flex puts all the popups among the rawChildren in the application’s SystemManager. This is where we can find them. So now that we know where to look, we need a way to distinguish the children that are popups from those that are not (rawChildren does not contain only popups). If we use only components whose base class is the standard UIComponent class (I think this is the case most of the times), there’s an easy way to know if an instance is a popup or not: the isPopUp property of UIComponent.

Whenever we create a new popup that extends UIComponent, the PopUpManager sets the isPopUp property to true. So, all we need to do is cycle through the application’s systemManager.rawChildren and check whether we find an UIComponent instance whose isPopUp property is true. In that case, we’ve got an application’s popup.

To demonstrate the concept, I’ve implemented the PopUpUtils class. It simply allows you to get all the popups inside an application instance, to discover if there are visible popups and to close all the popups. Let’s take a look at it.

package com.devahead.utils
{
	import flash.display.DisplayObject;

	import mx.collections.ArrayCollection;
	import mx.core.Application;
	import mx.core.IChildList;
	import mx.core.UIComponent;
	import mx.managers.PopUpManager;

	public class PopUpUtils
	{
		/**
		 * Returns all the popups inside an application. Only the popups whose base
		 * class is UIComponent are returned.
		 *
		 * @param applicationInstance
		 *   Application instance. If null, Application.application is used.
		 * @param onlyVisible
		 *   If true, considers only the visible popups.
		 * @return All the popups in the specified application.
		 */
		public static function getAllPopups(applicationInstance: Object = null,
			onlyVisible: Boolean = false): ArrayCollection
		{
			var result: ArrayCollection = new ArrayCollection();

			if (applicationInstance == null)
			{
				applicationInstance = Application.application;
			}

			var rawChildren: IChildList = applicationInstance.systemManager.rawChildren;

			for (var i: int = 0; i < rawChildren.numChildren; i++)
			{
				var currRawChild: DisplayObject = rawChildren.getChildAt(i);

				if ((currRawChild is UIComponent) && UIComponent(currRawChild).isPopUp)
				{
					if (!onlyVisible || UIComponent(currRawChild).visible)
					{
						result.addItem(currRawChild);
					}
				}
			}

			return result;
		}

		/**
		 * Checks if an application has visible popups. Only the popups whose base
		 * class is UIComponent are considered.
		 *
		 * @param applicationInstance
		 *   Application instance. If null, Application.application is used.
		 * @return True if there are visible popups in the specified application,
		 *         false otherwise.
		 */
		public static function hasVisiblePopups(applicationInstance: Object = null): Boolean
		{
			if (applicationInstance == null)
			{
				applicationInstance = Application.application;
			}

			var rawChildren: IChildList = applicationInstance.systemManager.rawChildren;

			for (var i: int = 0; i < rawChildren.numChildren; i++)
			{
				var currRawChild: DisplayObject = rawChildren.getChildAt(i);

				if ((currRawChild is UIComponent) && UIComponent(currRawChild).isPopUp
					&& UIComponent(currRawChild).visible)
				{
					return true;
				}
			}

			return false;
		}

		/**
		 * Closes all the popups belonging to an application. Only the popups
		 * whose base class is UIComponent are considered.
		 *
		 * @param applicationInstance
		 *   Application instance. If null, Application.application is used.
		 * @return The list of the closed popups.
		 */
		public static function closeAllPopups(applicationInstance: Object = null): ArrayCollection
		{
			var allPopups: ArrayCollection = getAllPopups(applicationInstance);

			for each (var currPopup: UIComponent in allPopups)
			{
				PopUpManager.removePopUp(currPopup);
			}

			return allPopups;
		}
	}
}

As you can see, the getAllPopups function returns all the popups inside an appplication instance. If the instance is not specified, then the current application is used (the one in which the function is called). The hasVisiblePopups is basically the same, except the fact that it stops executing as soon as a visible popup is found. The closeAllPopups function closes all the popups in the application.

Here is an example on how the PopUpUtils class can be used.

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
	pageTitle="Getting all the popups in a Flex application - devahead BLOG"
	layout="vertical" horizontalAlign="left"
	applicationComplete="{onApplicationComplete(event)}"
	viewSourceURL="srcview/index.html">

	<mx:Script>
		<![CDATA[
			import mx.controls.Alert;
			import mx.core.UIComponent;
			import mx.collections.ArrayCollection;
			import com.devahead.utils.PopUpUtils;
			import mx.core.IFlexDisplayObject;
			import mx.containers.Panel;
			import mx.managers.PopUpManager;
			import mx.events.FlexEvent;

			protected var counter: int = 1;

			protected function onApplicationComplete(event: FlexEvent): void
			{
				// Add 10 popups on startup
				for (var i: int = 0; i < 10; i++)
				{
					addPopUp();
				}
			}

			protected function addPopUp(): void
			{
				// Create a Panel popup setting a random position for it

				const X_OFFSET: int = 200;

				var popup: IFlexDisplayObject = PopUpManager.createPopUp(this, Panel);

				popup.width = 200;
				popup.height = 200;

				popup.x = X_OFFSET + (Math.random() * (width - X_OFFSET - popup.width));
				popup.y = Math.random() * (height - popup.height);

				(popup as Panel).title = "PopUp " + (counter++);
			}
		]]>
	</mx:Script>

	<mx:Button label="Add popup" click="{addPopUp()}"/>
	<mx:Button label="Are there visible popups?"
		click="{Alert.show(PopUpUtils.hasVisiblePopups() ? 'Yes' : 'No',
			'Are there visible popups?')}"/>
	<mx:Button label="Close all popups" click="{PopUpUtils.closeAllPopups()}"/>

</mx:Application>

The example application creates 10 popups on startup, then you can create additional popups, you can check if there are visible popups or you can close them all. I used a standard Panel to create popups instances. The X_OFFSET is useful only to avoid having the popups over the buttons, just for usability.

Tags: ,

Leave a Reply

WP Theme & Icons by N.Design Studio
©2009-2010 Andrea Bresolin. All rights reserved. - Privacy Policy
Entries RSS Comments RSS