Implementing IEventDispatcher

english mobile

Recently, I had to have a class that took arguments in its constructor and also was able to dispatch events. Rather than trying to extend EventDispatcher and worry about separating the arguments the rest of the class needed from the ones EventDispatcher needed, I decided to implement IEventDispatcher. Problem was, I hadn't done this in a while, and I couldn't remember the right way to do this and had no idea what project had an example of it. So, I went searching on the web and refreshed my memory that you need to include an EventDispatcher instance in your class and route your IEventDispatcher methods through that object.

I created some boilerplate code that I can just cut and paste to add IEventDispatcher support to a class, and I share it with you now.



//--------------Support for IEventDispatcher--------------//


private var _ed:EventDispatcher;

public
function addEventListener(type:String, listener:Function,
useCapture:Boolean=false, priority:int=0,
useWeakReference:Boolean=false):void
{
_ed.addEventListener(type,
listener, useCapture, priority, useWeakReference);
}
public function
removeEventListener(type:String, listener:Function,
useCapture:Boolean=false):void
{
_ed.removeEventListener(type, listener,
useCapture);
}
public function
dispatchEvent(event:Event):Boolean
{
return
_ed.dispatchEvent(event);
}
public function
hasEventListener(type:String):Boolean
{
return
_ed.hasEventListener(type);
}
public function
willTrigger(type:String):Boolean
{
return _ed.willTrigger(type);
}



Enjoy!

Updated 12/15/08:
Note that you'll need to put an instance of EventDispatcher in _ed in the constructor of the class that's implementing IEventDispatcher:

_ed=new EventDispatcher(this);

Updated 12/21/08:
Josh McDonald posted code that shows how to implement IEventDispatcher with boilerplate that doesn't require adding a line to the constructor.

More thoughts on Remoting

english mobile

As I mentioned in my last post, I've been working with AMF for the first time this week. I'd read about using AsyncTokens to be able to determine which call to a service resulted in which result, so from the very beginning I'd intended to use this. The problem I had was that when I looked at the docs for RemoteObject, I couldn't find anything that actually returns an AsyncToken. So at first I figured I couldn't do it.

But here's the thing. All of my commands to access the RemoteObject use static properties and methods, which essentially means that for each service there's only one RemoteObject that gets used from any object in the application that needs to call that service. These different parts of the application didn't know about each other, and I didn't want them to. Nor did I want to make these commands refuse any new calls before the old one was finished. So I had to make this AsyncToken thing work, or completely change the architecture of how I was calling AMF.

Finally, I found the documentation for mx.rpc.remoting.Operation (don't ask me how). It turns out that a remoting Operation is the method on the service that you're calling. When you call a RemoteObject operation, you're invoking the Operation Class's send method, so it seems that creating an AsyncToken from a RemoteObject call is as simple as myToken:AsyncToken=myRemoteObject.myService(whateverParameters). I'm not sure exactly how you're supposed to figure that out unless you happen to luck into the right information like I did, since there's no direct link between the language reference on RemoteObjects and that on Operation, and it's only referred to in passing in a parentetical expression in the RemoteObject "how to" type documentation.

One of my command classes needed to be able to accept a result and fault function from the instance that was calling the service, so I then needed to find a way to set a Responder on the token. The first thing I tried was simply to push a new Responder onto the token's responders Array. Let me save you a little time and tell you in advance this doesn't work. Instead, you need to use the AsyncToken's addResponder() method.

Thoughts on remoting

english mobile

The past week or so, I've been doing something that's new to me--retrieving objects using AMFPHP and integrating them with Flex. In the meantime, I've found that there are some things that are hard to find out about the whole process, so I thought I'd make a note of them here.

First, all the examples I could find easily used NetConnection. The code on these was so similar that I think there was one basic example that has been modified slightly by several different people and posted. I had better luck using RemoteObject, and I finally found an example of this.

The next thing I ran up against is that you have to use a RemoteClass alias on your Flex class that defines the object that is receiving the data. The docs are a bit misleading in that it sounds like you only need to use this if you are sending to a remote service and the service is Java based. However, if you read a bit further (I didn't at first), you can see that this applies pretty much to any AMF mapping. If you are sending data only from the service to Flex and you're not sending data back from Flex to the service, the only thing that matters about this alias is that it must match the $_explicitType variable in the object on the PHP side.

I also discovered a few things on my own. My classes extended EventDispatcher, and at first they didn't deserialize properly. We speculated that the fact that the class wasn't just a subclass of Object might have been the problem, but it turns out that extending EventDispatcher doesn't break serialization. My classes also had their own methods and some additional properties. We speculated that these were causing the problem, but it seems that serialization ignores these things. I think that if I were sending data back to PHP through the RemoteObject, I'd need to mark those properties as transient.

I think the real reason the serialization wasn't working was the last thing I discovered, which is that you have to have a dummy variable typed as your custom class in the same class as the RemoteObject that you're using to retrieve the values. This makes sure that the class definition gets compiled into the class where it can be used.

Oh, and one more thing... To a PHP programmer who's not familiar with ActionScript, a setter looks like something he can't serialize to. So it's probably better to just write up a description of the properties you're expecting to have set than sending the PHP person your actionscript class as is.

Filtering Bookmarks, Warnings, and Errors in Flex Builder

english mobile

Up until recently, I almost never kept more than one project open in Flex Builder at the same time. The reason was simple: if I was looking at Project A, I found it very confusing to see bookmarks or warnings from other projects in the Bookmarks or Problems panel.


Several months ago, I looked for a way to filter this, but for some reason I couldn't find it. Last week, I was more successful. If you click on the filter button () in either the Problems panel or the Bookmarks panel, it will take you to a dialogue where you can select an option that more suits your working style. I selected "On any element in selected project."
Now I can have multiple projects open at once without getting distracted.

Moving from Authorware to Flex

english mobile

I started out as an Authorware developer, and one reason I am now doing Flex is that Adobe announced the End of Development of Authorware just over a year ago. I saw that Flex offered a lot of the advantages of Authorware--it does a great job of integrating various media into a cohesive whole and you can make an application that runs from the web or the desktop from approximately the same code.

Adobe's decision left many people scrambling to figure out where they would go, so Randy Nielsen from the Flex documentation team worked with a few Authorware developers to get a stub page up when Flex 3 was released so that Authorware developers could document what their experiences have been to help ease the process of making the migration for those who felt that Flex was the best Authorware replacement for them.

At long last, I managed to make some time to add my 2¢ worth to the document. So I'm happy to announce that the Moving to Flex from Authorware page at the Flex documentation wiki has been updated. There is one section that I wrote that for some reason isn't included, and I feel it may be useful to some people, so I'm posting it here:

Using Flex files inside Authorware
In large existing projects, it might not be feasible to migrate the entire project to Flex over night. One strategy is to create new functionality in Flex and embed that in Authorware. When Authorware finally is abandoned, the Flex functionality will still be useful.

Flex Side
Flex and Flash have an object, ExternalInterface, that allows them to communicate with whatever application contains the swf file. Normally, this is used in a swf embedded in the browser to communicate with javascript that is written in the HTML page.
At the moment that the swf loads, the child components of the swf don't yet exist, so any attempt to set any properties on them will cause an error, which will probably stop your Flex application from proceeding any further. So you should wait until everything is created before initiating communication with the container. This means that you should run a function on creationComplete that will use ExternalInterface to call out to the container and tell it that it is ready to receive data. This function should also set up the callback functions, which are the functions inside your Flex application that are accessible to the container.
The container should then respond by calling a function and providing data your Flex application needs as an argument. This can be a user name, lesson status, or XML that represents a menu. The function should perform whatever parsing is needed on the data and set object properties based on the data.
When the user interacts with the swf, it should again use ExternalInterface to tell the container what happened.
Once you have created your Flex file, you should make sure to export a release build by going to Project>Export Release Build. This file will be smaller and run more efficiently than the debug build that is built by default.

Authorware Side
The Authorware file will have a Shockwave Flash Object ActiveX control icon in it. The development machine should have Flash Player version (Randy, what's the minimum version of the Flash Player for Flex 3?) on it, and you'll need to make sure that the users have at least that version installed.
Next, you'll need a calculation icon that sets up the path to your swf file so that Authorware can find it. This will start the loading process, which will culminate in the creationComplete event.
Once the creationComplete event fires, the swf will generate an event that can be seen in Authorware by using ExternalInterface. To catch this event, you'll need to use an Event Response on an Interaction icon. The response should be set up to respond to the FlashCall event. This seems to work best as a perpetual response on an Interaction that is below the ActiveX Sprite on the flow line, but above the calculation that sets the path to the swf.
The information contained in the #request property of the EventLastMatched variable will be an XML formatted string, so you'll need to use an XML parser object to access its contents. The same event response will trigger every time the Flex Application calls ExternalInterface.call, so you'll need to look at the name of the root element to see what "function" the Flex file thinks it is calling and branch based on that.
In the branch that you set up for the initial call where the swf tells you it is started, you should respond by issuing a CallSprite command to the Flash ActiveX Sprite icon that calls a function in the swf with the data you want to see in Flex. Other branches should contain logic to respond to different calls the swf sends with ExternalInterface.

Download the example files.

GroupingCollection example featuring GroupingFunction

english mobile

Several months ago, I built a dashboard example for a client that featured a calendar with a month view like you'd see in a paper calendar on one side and a week view on the other side. I wound up writing some fairly complex classes to handle the different breakdowns in how the data displayed. I also wrote a custom renderer for the calendar page and a different one for the week view.

And then I had to do some work with the AdvancedDataGrid and fell in love with the way this component "thinks" about data, with its HierarchicalData, HierarchicalCollectionView, and GroupingCollection. And, of course, I adore its styleFunction, as you might have guessed from my earlier TileList_withStyle and DataGrid_withStyle classes.

A few weeks ago, someone posted an example that showed a way to use GroupingCollections with controls that were not AdvancedDataGrid or Tree components. Let me tell you, that got my little cogs twirling. If only (thought I) you could use a function to decide how the items in a GroupingCollection grouped. Then you could use it to group dates into years, months, weeks, whatever floated your boat. So I went digging into the docs, and found that the GroupingField actually does have such a property.

And so the GroupingFunction example was born. This example illustrates how you can create a single array of objects that contain the dates to use for a Calendar application, then group and filter the data in different ways by using that array as the source for multiple ArrayCollections and GroupingCollections. These allow you to display that data in several different ways without a lot of manual parsing.





It also illustrates the following concepts:



  • Using a single itemRenderer with the TileList_withStyle component to present different appearances based on the styleFunction you use.

  • Using a Repeater to populate an Accordion control based on a data source

  • Using a single child component that gets reused between the children of
    the Accordion


I'd also like to point out that I'd have never been able to create this example if I weren't still looking for work. I'm sure you're probably loving being the recipient of all these free examples, but please return the favor by passing my name on to anyone you know who is hiring :-).



Updated October 21, 2008:

I changed the itemRenderer to show how you can set the blendMode on text to apply effects to it without embedding the font. I only set the blendMode on the lower label , so that the difference would be apparent.

Extended DataGrid with StyleFunction Example Posted

english mobile

A few weeks ago, I posted an example of an extended TileList that adds the styleFunction I've become so fond of with AdvancedDataGrid. I decided I'd look and see if I could do the same with DataGrid, and I found that, while it was challenging, I was able to do it. So I've posted my new extended DataGrid_withStyle and StyleableRenderer classes for you to use and enjoy. As always, View Source is enabled.