The V2 Component Event Model Part 1- EventDispatcher
September 24, 2003

After spending a bit of time familiarizing myself with the V2 component event "model", I thought I would write down some observations just to clarify this for myself (and hopefully others too).

The V2 component event model is based on listeners instead of callbacks (which was the foundation for V1 components).

With V1 components (in Flash MX), you would use something like "setClickHandler" to "register" a single function to "callback" when (in this case), the component was clicked on. You could specify the object that contained that function, or if you didn't, it automatically looked for the function in the _parent scope of the component. This was fine and dandy, but it was a little limited because you had to have one central code block that was waiting for that event to fire and send messages to all of the appropriate destinations.

Enter V2 component architecture. Being based on listeners instead of callbacks, this allows for a more robust way to handling events. Now you can register multiple objects to "listen" for an event and each object can "do it's thang" when the event it's listening for is "dispatched".

Flash MX actually came with a built in mechanism for implementing listeners called ASBroadcaster. This was an internal (and undocumented) object that allowed you to quickly set up a broadcasting object and also provided a way to add/remove listening objects to it as well as broadcast events to those objects. However, there was a little bug discovered in it that resulted in "only every second eventhandler being called, if listeners are removed in the eventhandler". There were also several AS based listener event models that were written to try to overcome this deficiency.

ASBroadcaster still exists in FP7 and it seems to fix this bug when your movie is exported as a F7 swf. Note that you now have to use "AsBroadcaster" (lower case "s") in F7.

I said all that to say this...

V2 components implement a listener model, but do it without using AsBroadcaster. There is a class called "EventDispatcher" (core/mx/events) which is used to add this broadcasting (called dispatching in F7) functionality to UIObject (the base class for all components).

Essentially, it works in much the same way that AsBroadcaster does:

1) You set up an object as a dispatcher by running "EventDispatcher.initialize(dispatchingObj)".

2) You can add or remove listeners ("dispatchingObj.addEventListener('event', listeningObj)" and "removeEventListener(listeningObj)").

3) You can broadcast/dispatch events to those listeners ("dispatchingObj.dispatchEvent(eventObj)").

However, there are a few differences to be aware of:

1) It appears as though EventDispatcher "categorizes" it's listeners based on the type of event(s) it is registered to listen for. Whereas AsBroadcaster (as far as I know) just stuck all of it's listeners into a single "listeners" array (and broadcast ALL events to ALL listeners - if a listener didn't have a particular handler defined, it silently failed), EventDispatcher actually creates seperate arrays for each unique event, so that when a particular event is dispatched, it looks only in the array associated with that event. A subtle but important difference.

2) When dispatching via EventDispatcher, instead of passing the event and a bunch of parameters, you now pass a single "event object" that contains any properties that you want to pass to your listening objects. A couple of important properties to note in this object:

"type" - this is a required property that allows you to indicate which event you want to dispatch.
"target" - this is an optional property that allows you to pass a reference to an object into the listener's handler so that you can act upon that object. If you leave this out, it will default to the dispatching object.

3) Before your dispatcher passes the event being called onto it's listeners, it actually will call a method internal to itself (kinda like a "click handler" in V1 components). This is cool because it allows you to have the dispatcher do something on itself if you ever want it to (thereby emulating the functionality of the callback model in V1 components). In order to make use of this functionality, you need to create a method on your dispatching object called [eventName + "Handler"]. So if you have a "click" event, you would call it "clickHandler". It will pass the event object mentioned in #2.

4) The dispatcher will accept objects, movieclips or plain functions as listeners. Depending on which of these you use as your listener(s), there will be slight differences in how you set up your listeners.

If you set up your listener as a movieclip or an object, there are 2 ways in which you can set up your listener to capture the dispatched event: a) Create a method on that movieclip or object that is the same name as the event that the movieclip or object is listening for. So if you are listening for a "click" event, you can set up "myObj.click = function(eventObj) { };". An "eventObj" parameter is passed to the method. b) Create a method called "handleEvent(eventObj)" on your movieclip or object. This then becomes a generic "interface" through which your listener can handle event dispatches. All event dispatches can come through this method. This means that you must look at "eventObj.type" in order to find out which event has been triggered and run the appropriate code.

So what does this all mean when working with components? Well, here is a simple example. Let's say you have a button component on stage called "submitBtn". You could set up a listening object by doing this:

// Listening object contains a function with the same name as 
// the dispatched event
var listeningObj:Object = new Object();
listeningObj.click = function(eventObj:Object):Void {
 trace("submitted by " + eventObj.target);
}
submitBtn.addEventListener("click",listeningObj);
Or this:
// Use a central "handleEvent" function to mitigate all events
var listeningObj:Object = new Object();
listeningObj.handleEvent = function(eventObj:Object):Void {
 if (eventObj.type == "click") {
  trace("submitted by " + eventObj.target);
 }
}
submitBtn.addEventListener("click",listeningObj);
Or you could just do it the old V1 component way like this:
// Old school click handler style
submitBtn.clickHandler = function():Void {
 trace("submitted by " + this);
}
One other cool thing that I didn't realize until Grant and I were talking in the wee hours of the morning. As I mentioned above, you can set up a plain function as a listener. At first, I kinda brushed this off and didn't think much of it. However, here's where this little feature becomes kinda handy...

Let's say you want to have the ability to listen for the same event from different dispatching objects. If you set up your listening object, and then set up a "click" method on it, the only way to distinguish which dispatcher sent out the event is to look at the "target" property (mentioned above) of the event object passed to that function and run and if statement to do different stuff for different dispatchers. However, if you set up a series of plain functions as listeners, you can actually specify which one you want to execute for any given dispatching event.

// Use plain functions as listeners and specify which one
// you want to listen for any given event from any given
// dispatcher
function handleSubmit = function(eventObj:Object):Void {
 trace("submitted!");
}
function handleReset = function(eventObj:Object):Void {
 trace("reset!");
}
submitBtn.addEventListener("click",handleSubmit);
resetBtn.addEventListener("click",handleReset);
Of course, you could also do this by setting up a new object for every dispatcher, but this works too.

Whew. In future installments, i'll be looking at UIEventDispatcher and LowLevelEvents. Stay tuned...

Posted by philter at 11:30 PM | Comments Disabled
Some newfound insights into component architecture
September 16, 2003

After digging into the component classes a bit (more specifically, the base classes UIObject and UIComponent), I came across something quite strange in my eyes. One of the functions of UIObject (which is essentially the base class for all components - it extends MovieClip directly) is to support events, so that if you extend UIObject, you will be able to use these "event dispatching" capabilities in your subclass.

However, after looking in the UIObject class file, I noticed that the only things that are there in relation to events is a few "empty" functions like "addEventListener", "removeEventListener", "dispatchEvent", etc. So it seems that there is actually no event implementation in the class at all!

Then, I proceeded to look in the "EventDispatcher" class file which is the base class for all event dispatching and listening (at first glance, it looks like EventDispatcher is functionally equivalent to ASBroadcaster in MX). This didn't really help me either in terms of how UIObject uses it to add/remove listeners and dispatch events.

Then, I went to the FlashCoders list because I figured some highly intelligent person would be there who would be able to give me an answer to this very fundamental question. And who steps up to the plate...? Peter Hall (flash guru extraordinaire) and Nigel Pegg (component engineer).

Take a look at the thread.

Anyway, to sum it up, what I learned was this...

Essentially, there are classes called "mix-ins" in the V2 component architecture. Their purpose is to add functionality to other classes without actually creating subclasses. Why not just put that functionality in the first class to begin with? Well, first off, you want base classes to be fairly generic so you don't necessarily want to clutter it with a bunch of methods that won't be used in most situations. Second, by doing this, you save file size because your base class is lighter and you only download the stuff you need in that class, as well as the other classes that are relevant to what you are doing in any given project.

Anyway, it seems that mix-ins work in the following way (I hope i'm getting this right):

1) Your mix-in class implements a set of methods/props that you want to be "mixed into" another class to extend the functionality of that class.
2) Your mix-in class generally has an "Initialize" method that is passed a reference to a class and adds the methods/props from point #1 to that class by looping through an array containing the method/prop names you want to add, and copying references(?) of those methods/props (from an instance of itself created inside the mix-in class) into the prototype property of that class. Don't know if that made sense...
3) What you end up with is a class that has a bunch of new methods/props that were added on the fly. This proves that "prototype" can actually be very useful when trying to make classes act "dynamic".

So why is this relevant in the case of UIObject? Well, I don't know if the implementation of all of this really is relevant, however, the concept is. Getting back to "event dispatching", there is actually another class called "UIObjectExtensions" (described as a static helper class by Nigel) which is used to add the event functionality to UIObject. When the "Extensions" method of UIObjectExtensions is called, it sets up event dispatching capabilities for UIObject.

So when is this Extensions method called? Well, it's actually called inside of the UIObjectExtensions class itself, so that it automatically runs once that class initializes. How is this connected to the actual UIObject library symbol? Well, if you look inside the "ComponentFLA" file library, you'll see a symbol called UIObject (which is connected to the UIObject class) and in frame 2 of that symbol, you'll see one symbol that is connected to UIObjectExtensions. So, when you drop that UIObject symbol into your custom component, everything should work like a charm.

Hope I haven't missed too much...

Posted by philter at 11:08 AM | Comments Disabled
Upacking Component Files (.swc)
September 11, 2003

You've probably already heard about how components work in MX 2004. Well, if you haven't, when you create a component, you can actually generate a file with a .swc extension from the component you build in Flash. This is an external file that you can share with others without having to share your component code. From the docs, it sounds like the .swc file is actually a compiled version of the component, but I wondered...why not just have it as an .swf file? What's so special about this .swc file format?

After examining the file a little more closely, it turns out that you can actually unzip the .swc file (I used Winzip). When I tried that, to my surprise, it unzipped a plethora of stuff. Here are some of the things I found:

1) The actual compiled component file (.swf). I assume you could also just take this file and use loadMovie() to use it at run-time.
2) A graphic file (a .png in this case) that is used as the icon in the library (and component panel?).
3) A bunch of files with .asi extension. Upon opening one of these, I noticed a few things. It looks like these contain content from the actual classes that are used within the component. However, the code has been stripped down to just the member names (ie. property and functions), member access and data types. None of the actual implementation code is there. The other thing is that the class has been converted to "intrinsic". I'm a little curious as to what this keyword actually does since all of the built in classes seem to use this as well.
4) A file called "catalog.xml". This is maybe the most interesting part of it all, as it contains a bunch of data that I assume is to be used in the Component Inspector(?), but I didn't really understand a lot of it just by looking at it. It listed a bunch of classes associated with the component as well as actual assets used in the component. I'd love to get more details on exactly what all this does.

It also listed an xmlns located at http://www.macromedia.com/flash/swccatalog/7. Not sure exactly what that's doing, but when I go to that url, it just redirects me to the Flash product page.

Anyone have any insights?

Posted by philter at 02:43 PM | Comments Disabled
AS2 features only for compile time?
September 10, 2003

One of the nice features of having a class based language is the fact that you can hide your implementation behind private methods, and expose only the methods/members you want to be "public". The fact that AS2 implements this feature is cool since AS1 using prototype didn't really allow this (without some crazy workaround). However, the Flash Actionscript docs include this statement:

"...note that member access control is a compile-time only feature; at run-time, Flash player does not distinguish between private or public members."

This seems to be a very important statement. This means that the checking is done to prevent any calls to those private members WITHIN a swf, however, in theory, you could actually call those private members from another loaded swf. So it doesn't seem to allow truly private access.

Also, I would have guessed that one of the advantages to having a strong typed language would be to have processing speed increases. I don't know how the player works internally, but you would think that if a variable is typed, the code could be processed more quickly because it doesn't have to do type checking at run-time. However, according to Grant, these strong typed variables get compiled down to "typeless" variables in bytecode. Again, it seems that the typing is only for compile-time checking. Maybe that's to support backwards compatibility...?

Posted by philter at 10:01 PM | Comments Disabled
Flash MX 2004 Pro - My first day
September 10, 2003

Well, just like a million other people, I went and downloaded the trial version of Flash MX 2004 Pro. After spending a little bit of time in it, and reading through some of the docs (which I must say seem to be a lot better than the ones that came with MX), I can honestly say that I can't wait to actually build something with it.

Here are some of my first impressions in my first 24 hours with MX 2004 Pro:
1) The new file tabs rocks.
2) It's very simple to connect an AS2 class (which must exist in an external AS file) to a movieclip in your library. All you have to do is right click on the symbol in your library, choose linkage, and type in your AS class (including package). No more Object.registerClass!
3) I've already seen the WebserviceConnector in action, so that's pretty cool. I also just played around a bit with the XMLConnector, and one neat feature is that when you select an XML file, it actually allows you to visualize the structure in the component inspector and bind UI elements with specific nodes...all without writing any code. However, at first glance, I can't seem to see how it works for extensible XML structures (ie., if you don't always have the same number of nodes at any given level in the tree).
4) Is it just me or are the new toolbar icons really cool?
5) Gotta love the added compile time checking with AS2 and strong typing. So far, finding errors has been a breeze.
6) The docs that come with MX 2004 Pro are a lot more in depth in terms of explaining some of the stuff on the coding side of things. I think the "Using Components" doc will come in really handy for a lot of people. It's just too bad that there is missing documentation for a lot of the components that come with MX 2004 Pro.
7) Global find and replace...with regular expressions!
8) Noticed that the Combobox and Tree components use animations to expand/collapse, but I couldn't seem to find a way to turn it off (without messing with the class code). Anyone know how?
9) Anyone know what a delta packet is?

Posted by philter at 09:37 PM | Comments Disabled
Top 6 highlights from last night's WWUG meeting
September 04, 2003

We had a great time at the WWUG meeting here in Edmonton, Alberta, Canada (even though we were left off the map at the start of the preso :( Anyway, here are my top 5 highlights of the evening:

6) The organizers (Grant, Michael and I), and a few other lucky people got a cool beaded necklace with a Flash logo (can you spell computer geek?) provided to us by a local bead necklace manufacturer (beado.com I think). He approached MM with them, so maybe you'll be able to get one too in the future.

5) The fact that just as soon as the presentation started, we were prompted to download the latest version of Flash Player. Stupid player upgrades ;)

4) Seeing Chris Stans do his victory "dance" when his name was called for the Studio MX 2004 giveaway. It figures...the "Adobe guy" wins the MM prize.

3) Breeze Live - That was one sweet presentation UI. It was cool to be able to type in questions and have them answered as the presentation was going on (although there seemed to be a question about every 5 seconds at some points, so it was difficult for the people answering to keep up). Also, some people complained of not having audio, or the video being way behind the audio, or video not even showing up. Thankfully, our connection was good enough to never skip a beat. Sure, the presentation probably only ran at a few frames per second, but I don't think that was much of a hinderance. Not once did our audio or video cut out and everything seemed to synched up really well. Good job MM!

2) Seeing the demo of the WebService component and the fact that when you set the link to the WSDL, the Flash IDE automatically hit the URL and displayed the available methods and parameters. I know that other software dev. IDEs already do that but still, I thought it was cool.

1) The people! We had somewhere in the mid 80's in attendance (not bad for a smallish town in the frozen north :), and it was standing room only. It was really awesome to see so many familiar faces (former students, workmates, classmates) and to meet some new faces as well. Seems that Edmonton has a thriving Flash developer base, and hopefully we can continue to tap into that in future meetings.

Other than that, the presentations were fairly "surfacy", which is fair I guess, since there was a lot of stuff to cover and a wide range of skill levels represented in the audiences.

If MM is listening...I think I can speak for everyone in attendance in Edmonton when I say that we REALLY hope that you will continue to do more of these events in the near future. It would really be great to have presentations that focused on a specific product and went into more detail with the time given.

Good show MM!

Posted by philter at 01:19 PM | Comments Disabled
Edmonton Flash Users Group - The Big Meeting!
September 02, 2003

Finally got my blog back up after switching servers to CFMX. If anyone is setting up an MT blog for the first time, you'll save yourself a lot of time by making sure you set the permissions of your blog folder to read/write/execute/DELETE (not sure what I did differently the first time). The MT docs say you only need to set it to read/write/execute. Anyway...now that I can finally post again...

Sept. 3 is only a day away, which means that tomorrow is your first chance to see a working preview of MX 2004. That's right, we are now officially a MMUG and will be participating in the world wide MMUG meeting. You've probably read on hundreds of blogs about the next version of Flash and now you get to see it in action. We will be meeting at 7:30 pm at Guru Digital Arts College. They have a beautiful space they will allow us to use for this and future meetings!

We will also be raffling off a copy of Studio MX 2004 to one lucky individual. You MUST be in attendance to win

See efug.org for address and details.

We're expecting a large turnout, so make sure you get there on time (or early) for a good seat!

Posted by philter at 11:13 AM | Comments Disabled