Bucket Brigade Pattern is not Dead in AS3

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.

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:

Re-dispatching events

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?

8 Replies to “Bucket Brigade Pattern is not Dead in AS3”

  1. pls ignore.
    just subscribing to this thread – to see if there’s an answer on how people are doing this for deeply nested object models.

  2. Hi Jesse.

    I’ve been working alot with the issue in question.

    I´m overriding the initializeComplete method, calling super and add my listeners in the systemManager scope.

    Now all my components dispatch and listens in the same scope, solving the nesting bubbling problem.

    Any comment on this solution?

    example :
    In Class extending Image:

    override protected function initializationComplete() : void {

    systemManager.addEventListener( CustomEvent.LOAD_PHOTO,loadPhoto );

    }
    private function loadPhoto( e : CustomEvent ) : void {

    this.source = e.photoURL;

    }

    Deeply nested object somewhere else in application:

    ( MouseListener added )

    private function onClick( e : MouseEvent ) : void {

    systemManager.dispatchEvent( new CustomEvent( CustomEvent.LOAD_PHOTO, “http://domain.org/photo.jpg” ) );

    }

    /Edgy

  3. Jesse,
    I’m no expert in this stuff but I’ve created a few non-GUI objects that simply extend EventDispatcher to enable event dispatching… Seems that events are working fine for these domain objects even though they’re not on the display list… but now you’ve got me curious to double check.

  4. OK, read your post in the last few minutes of my lunch break and quite obviously missed the point… so what you’re really interested in is some kind of event bubbling within a hierarchy of domain objects and then possibly traversal from domain objects to the display list hierarchy for further bubbling, right? Interesting… I’ll be curious to see what else is posted… Thanks for all the great content on your blog!

  5. I feel like I’m pointing out the obvious simple solution, but here goes.

    My coworker recently had the same issue where he needed bubbling in non-gui classes. I offered the following suggestion:

    “Try extending DisplayObject.” It worked perfectly.

    That’s proof enough for me.

  6. Hi,
    another approach, depending on your app, is to build an event manager just for the type of events your app needs. It works for me since I needed custom events anyway. Your core classes can handle the bubbling.

    My particular app is a non-flex component architecture, one that is required to load its own datafiles at runtime to determine its appearance, not just its content. I don’t need many components, just a dozen or so, but they need to have more malleable parameters than Flex components, and the app needs to be lightweight.

    Since these are my own components I handle their events in a 2 step process. Every sprite that is owned by a component gets a capture object assigned to it, which listens to the basic AS events. Mouse events, etcetera. The capture class has a bit of internal state to determine what the user really did. The capture object is owned by a component.

    Anyway once that event is sent up to the parent component, the component creates a UI Event which I ID with whatever string I want, for example, a button-drag-out, or a control-slider-press. Each sub-component reports up to its parent via basic inheritance of a main component class. I.e. – a bubble up function. Based on the type of component it deals with events appropriately, or bubbles them up further.

    It winds up being elegant but its one of those things you need to keep as simple as possible…

  7. I tried Steven’s solution within the Gaia framework, but now the class that was extended is silently failing to construct. Very bizarre..

Comments are closed.