I recently was working on an application, and needed to listen to KeyBoardEvent dispatches from the stage. This isn’t usually that much of an issue, except when your component needing to listen to these Events is created as part of the application creation process.

Refresher… I hope…

As a reminder the start up process of the application happens AFTER its children are created. This is notified via the SystemManager to the application via the FlexEvent.APPLICATION_COMPLETE event, and from there we can immediately access the stage and do whatever we want (e.g., listen to the stage for events, apply stage properties for fullscreen, etc.).

For more details consult the Flex documentation: About startup order

ApplicationComplete… ok… So just start listening there?

Well, yes and no. It really depends on what you’re trying to accomplish. In the example of setting stage properties, sure… That’s most likely going to be a global entry/exit point for things like full screen mode, etc.

But for me, I have a component created and I want it to register itself with the Stage to listen for KeyBoardEvent dispatches. Specifically speaking, I want to listen to the ESCAPE key in my component, and not have to worry if it’s in focus.

Another use-case would be a hidden console, or some kind of hidden debug entry. Sure I could implement it directly in my Application container directly after ApplicationComplete is done, but that’s kinda nasty. And if I took that approach for a lot of things, my app container becomes big and bloated.

Let’s take it even further and assume we have a growing application container, and today have 15 components that all want to listen, but later we might have 100. It would be rather lame to do something like the following:

[sourcecode language=”actionscript3″]
component1.initialize();
component2.initialize();
[/sourcecode]

and so on…

No… See, I want a component that conforms to SRP. But that’s a matter of preference…

Get to the point… what do I do?

Well, it actually turns out to be rather simple. But you have options.

During a Flex component initialization, you have access to the SystemManager on the component via this.systemManager, and can do one of two things.

In both cases:

[sourcecode language=”actionscript3″]
public function MyComponent():void
{
//NOTE: You can alternatively listen for FlexEvent.PREINITIALIZE Event and beyond
this.addEventListener(FlexEvent.CREATION_COMPLETE, this._onCreationComplete, false, 0, true);
}
[/sourcecode]

Quick and Dirty:

[sourcecode language=”actionscript3″]
private function _onCreationComplete(event:FlexEvent):void
{
this.systemManager.stage.addEventListener(…);
//-or-
this.systemManager.stage.displayState = StageDisplayState.FULL_SCREEN;
}
[/sourcecode]

Probably More Proper:

[sourcecode language=”actionscript3″]
private function _onCreationComplete(event:FlexEvent):void
{
this.systemManager.addEventListener(FlexEvent.APPLICATION_COMPLETE, this._onAppComplete, false, 0, true);
}

private function _onAppComplete(event:FlexEvent):void
{
//same as example above, but accessing this.stage instead
}
[/sourcecode]

Why’s that more “proper?”

Well, in most cases, you’re fine doing the prior example.

But in a more complex application architecture where modules or sub-applications are used, the SystemManager will evaluate the stage and can be a tad bit unpredictable depending on your setup/startup. It’s interesting to see how the Flex SDK team has managed to keep track of the stage object, and will return the appropriate one in most cases. But as they say “better to be SAFE than SORRY!” You can assume the component’s stage property is the proper one you really want.