I’d like to know how others are handling the fact that Event bubbling only works with classes that extend GUI objects (aka, DisplayObject).
If you already know how event bubbling works, you can skip to my problem.
Background on Event Bubbling
Event bubbling is dope. It allows you to have a deeply nested MovieClip (View) dispatch an event and “let you know it did something relevant”. The “let you know” part is accomplished by the bubbling being set to true for the dispatched event, and the “relevant” part is making the assumption you’ve listened for the event type its dispatching.
Normally, whether in Flash or Flex, you listen to events of your children. In these Composite classes, (aka MovieClips that holder other MovieClips, Views which hold other Views), you register for events on those children… or even yourself. If you are attaching a Button inside a Form, your Form will want to know when the Button is clicked on. Your Form will listen to itself to know when it’s added to the DisplayList; when that happens, its stage property is not-null, and it can then size itself to the maximize size of the SWF.
There is a lot more going on here, though, and a lot more your can do. Lets say you have multiple Forms of varying complexity, and each contains Forms within Forms. A real-world use case is medical software. The amount of forms you have to fill out, and the relation between fields, forms, and other data located elsewhere as well as on the same page is quite complex. If a patient has an allergic reactions to surgical gloves, then this needs to update a Form in another area.
A lot of times, you can cheat with Model View Controller. You have all your Forms bind themselves to the Model (_global variable), make their changes, and others who are also bound to the same Model will be informed of those changes. That’s fine if all your Views are nice and self-contained. However, if you’ve been in GUI development for any length of time, it’s never that easy. Sometimes deeply nested Views need to modify the way another View that contains it. They can do this via bubbling events up. Eventually, a parent up the chain who cares can intercept that event in his event handler function, and do as he desires.
Need a simpler example? Modal Document Interfaces, like the FlexMDI one, allows you emulate Windows Explorer using Flex inside the browser. One key component is z-depth; aka, “who is in front of who”. If I click on ANYTHING within the Window, I need it to bubble an event up letting me know that it is now the focus, and therefore, I need to draw it on top of everything by swapping its depth higher than every other Window.
“But Jesse… why not just use Capture to true for the Event. That way, you can intercept the MouseEvent BEFORE it even gets within the Window’s contents?”
…yeah, I could I guess. Ok, how about this: Creating itemRenderers in a List or DataGrid. Some itemRenderers have buttons within them. How do I “know” that one particular button was clicked on? Like my CheckBox example from the past, you first dispatch the event from the itemRenderer with its bubbling property set to true, and you then listen for it ON the DataGrid. The problem is, DataGrid doesn’t dispatch your custom event name most likely. Therefore, Flex won’t compile your shiz. Quickfix is to extend DataGrid in MXML, define your event in the Metatag, and you’re then good to go. An itemRenderer is like I think 4 Sprites deep… bubbling your custom Event will shoot it up the tree to you.
Hopefully by now you can at least have some ideas on how this can help you. Granted, MXML or AS, if you want to retain strict-typing, you still have to define frikin’ Event metatags on all the intermediatary Views EVEN IF they have no clue an event is bubbling all through them. Failing to think of a witty Dark Matter comment. Some could view this as breaking encapsulation if you did not define all of your metatags correctly as well as writing cleanly defined event names.
Did you know event bubbling ONLY works on objects in the DisplayList? That’s right, anything that doesn’t extend a GUI object cannot participate in event bubbling. Additionally, this includes GUI children that have been removed from the DisplayList. This also includes not just the bubbling phase, but also the capture phase. Now, if you have a Form-A that contains Form-B, which contains Form-C, and all are added to the DisplayList, an event generated in Form-C will bubble up to the top.
However, if you remove Form-A via removeChild, the event will no longer bubble up. Form-A can still listen to bubbled events from Form-C and regular events from Form-B, but all events will stop bubbling at Form-A; they won’t propagate to your application.
This is ok for GUI objects. However, for non-GUI (faceless) code, this makes it really tedious to bubble up events from deeply nested object models.
The use-case I’m referring to is the Bridge Pattern. We’re using it in 2 cases for out video players at work. The first abstracts the many types of NetConnections you can make to play video. Generic Flash Media Servers in the office for testing, Akamai and their Will Law special sauce, Limelight and their in-flux API’s, and good ole’ progressive video that does jack and is a mere formality. The second abstracts the various NetStream implementations from progressive video, streaming video, and live video. Combine these 2 with psuedo-abstract classes to encapsulate the insanity that is the non-cross platform NetStream and his “maybe” asyncronous events and you end up with Composition soup.
It looks and works damn good, mind you, but there is one problem; having those above who just want to play a video and display status about said video know what the heck is going on. For example, if you want to create a simple video player, you create a NetStream, listen to his events, and draw a GUI. However, things are never that simple for more complex video players that you have maintain for years. The Flash CS3 Video Player, not including all the captioning and other base classes, is 32 classes in just the fl.video package alone.
You’ll get nested object models. These nested object models one would think would be dope for event bubbling… but no, only for Flash Developers who still extend MovieClip for everything.
Here’s a visual example:
I’m starting to change my mind about implementing IMXMLObject for some of my classes I like to define in MXML within Flex. While easier to write, some Mediator somewhere has to know about him, listen to his events, and bubble the mofo’s up manually. While you can define events in interfaces, I’m not getting code hints, nor compile errors in Flex 3 Beta. I was so burnt out Thursday, I was 1 millimeter away from re-writing some of the base classes to extend Sprite and use composition for all the networking classes so Event bubbling was easier to do. I basically have to dispatch the same events in 3 classes.
How are others handling this? If not for the Bridge pattern, than for deeply nested object models?