Archive for the 'ActionScript 3' Category

New: Flex on Google App Engine - proof of concept and source code

I just updated The GAE SWF Project to add the proof-of-concept Google App Engine Flex 3 client. The source code download now includes the source code for the Flex project.

The Flex client works exactly like the Flash 9 client and shares an almost identical codebase. 99% of the framework is the same.

I'm going to document that differences, etc., but it's past 1am at the moment and I need to sleep!

The GAE SWF Project

The GAE SWF Project: Knowledge and tools to help you build Flash and Flex apps on Google App Engine

Today I'm releasing The GAE SWF Project, a resource of Flash and Flex-related knowledge specifically aimed at getting you up and running quickly with Google App Engine. If you want to skip all the details and start playing with it, skip to the Getting Started section.

Everyone else, read on!

When Google announced Google App Engine last week, I couldn't believe what I was hearing. It was as if someone had said, "Hey, Aral, tell us what your perfect development environment is and we'll build it for you."

In recent weeks, I had started playing with Python and Django and experimenting to see whether I could use it to build the web application for the Singularity web conference that I'm organizing at the end of October. Turns out that I could not have picked a better time to invest in learning Django and brushing up my Python as Google App Engine is heavily influenced by (and supports) Django and is written in Python.

A framework for the Singularity Conference

Singularity is shaping up to be a really great conference. I'm honored to have a constantly-expanding stellar line-up of speakers and yet the sessions are just one very important aspect of the conference. I find that you get as much out of your social interactions with speakers and other attendees at conferences as you do from the sessions. And Singularity is no exception.

The Singularity conference application is not something you will login to on October 24th and never visit again beyond October 26th. On the contrary, I plan to launching the application as early as possible and add features as we go so that we can start building the community around the conference. This is essential for the organization of the local conference hubs, for building friendships months in advance of the conference, and so that you can influence what the conference ultimately becomes (you do not have to attend the conference to join the online community.)

When I initially announced the Singularity conference two months ago, I stated in the About page that Singularity would have a "focus on open source, the community, and on giving back."

Today, I'm taking the first step towards delivering on that promise by releasing the initial underpinnings of a framework that will eventually power the Singularity conference web application. I present to you The GAE SWF Project.

The GAE SWF Project

The GAE SWF Project (hey, Google chose the name, I only provide the juvenile attempts at humor) is a resource of Flash and Flex-related knowledge specifically aimed at getting you up and running quickly with Google App Engine. The initial release contains a proof-of-concept Flash 9 client showcasing a pre-alpha version of The GAE SWF Framework. The framework is a very light-weight combination of Python and ActionScript 3 that uses some of the best open source components available today on the Flash Platform and Python ecosystem. It is inspired at its core by best practices and a pragmatic approach to application development.

The proof of concept (and, indeed, the whole project) specifically targets Google App Engine. This is by design. The framework is not a generic one (although, by all means, feel free to get inspired and port it if you wish). The dedicated focus is part of the appeal. It means that we can make things simpler.

There will be no abstraction for the sake of abstraction and no premature abstraction; the framework will evolve by encountering real-world problems and solving them.

Finally, keep in mind that you are viewing the fruits of three days of work at the moment (this, in itself, should be testament enough to how easy -- and fun -- Google App Engine makes development). It is early days but I feel that we've made a good start. I hope to hear your thoughts and feedback in the comments.

The Proof of Concept

The proof of concept is built on Google App Engine using Google's webapp framework.

It showcases several fundamental architectural considerations, the most important of which I've outlined for you below.

HTML and Flash in a tree...

You use handlers in app.yaml to host a mix of Flash and HTML content, including the Flash Remoting gateway, in a single Google App Engine app.

Embed Flash content using SWFObject

SWFObject is the way to embed Flash and Flex applications in your HTML. Use it. 'Nuff said.

Deep links

You implement deep linking using a combination of server-side Python and SWFAddress so that both SWFAddress-style and regular URLs are supported. Regular URLs are translated to SWFAddress-style hash/anchor URLs on the server.

Thus, both of the following URLs are valid ways to reach your profile page on the proof of concept Flash 9 client:

Regular URL:

http://gaeswf.appspot.com/examples/initial/profile

SWFAddress-style URL:

http://gaeswf.appspot.com/examples/initial/#/profile

Flash content that obeys browser text-size changes

Users with poor eyesight or in environments with reduced-visibility (such as bright sunshine outdoors) may want to increase the size of the text displayed in the browser. By default, Flash and Flex content does not react to these text-size changes. However, it is possible to make Flash content obey browser text-size changes and the proof of concept implements one such method that does not involve any alterations to the Flash app.

(You can read more about similar issues -- and see some juicy Flash myths debunked -- in my review of the talk I gave at Highland Fling this month titled Bare-naked Flash: Dispelling myths and building bridges.)

PyAMF

PyAMF is a Flash Remoting implementation for Python. It has a dedicated and responsive group of passionate developers working on it, led by Thijs Triemstra, Nick Joyce, and Arnar Birgisson. On Tuesday, the team released PyAMF 0.3 with support for Google App Engine.

The GAE SWF Framework uses PyAMF as a core component to communicate with the server and the various Google App Engine APIs. It is currently running PyAMF 0.3.

The PyAMF gateway is setup as a regular mapping, and mapped to /gateway in app.yaml.

Users API

You use the Google App Engine Users API to login and out of the Flash application. The current Flash 9 proof of concept implements one of three possible ways of handling logins (see the note in my earlier blog post about the other two ways.)

Intelligent forwarding after login

When you hit a deep link in the application without logging in, you are automatically forwarded to the link after you login. This is a behavior that you are accustomed to seeing (and expect) in HTML-based applications but I have rarely seen it implemented in Flash and Flex applications.

DataStore API

The Google App Engine DataStore is a massively scalable database based on Google's Bigtable (the same distributed database that powers their search and services like Google Earth).

The proof of concept has a profile section where you can fill in your name and a URL (the Users API currently does not provide your GAE app with the user's name, just their email address). This data is saved via PyAMF and the DataStore API.

(All server-side services are in the /services package.)

Client-side and server-side validation

The Profile Screen shows you how to implement two different types of validation: simple client-side validation and server-side validation.

The Name field performs simple client-side validation that stops the user from submitting the form without entering a name.

The URL field, on the other hand, actually hits the server and asks the DataStore to verify that the URL is valid. When you think about it, it makes sense to use server-side validation code to validate more complex data types using the exact same code that the DataStore API uses.

The user experience is managed via visual cues that are carefully scripted using the excellent KitchenSync AS3 sequencing library by Mims Wright. (Mims just added me as a project member so I can contribute a small update I blogged about earlier.)

(I'm still working on tweaking the timing of the type wait duration for firing the server-side validation code to make it as seamless as possible.)

As the framework develops, I know that the KitchenSync library is going to be an essential, core element, and I look forward to contributing back as much as I can to the project.

Mail API

The proof of concept also makes use of the Google App Engine Mail API to send email confirmations to your Google Accounts email address after you update your profile.

When initially working with this, I was searching for a simple way to monitor the mail that was being sent from the app. Although the Development Web Server allows you to specify an SMTP server when you start it, I couldn't get it to work with either GMail or my web host's mail server. And setting up sendmail or postfix was a pile of worms I didn't want to sample.

Instead, I found a simple, open source SMTP server written in Python that's perfect when developing locally with the Development Web Server. It's in The GAE SWF Project app that you can download. To start it, simply change to your The GAE SWF Project folder and type:

./monitor_mail

You will see all email sent from your application in the Terminal window. (Note: I run on a Mac and all the commands in this article are meant to be run in Terminal on OS X. You may need to tweak them slightly for your operating system of choice.)

CSS, etc.

I may introduce myself as a Flash Developer but that doesn't mean that I don't care about the rest of the web. With good friends like Andy Budd, Richard Rutter, Paul Annette, and Jeremy Keith living almost a baseball-bat-wave away from me, I'd be scared silly implementing a new site with anything less than pristine markup. So that's what I've strived for here and I hope I've at least come close. (I did use one <br/> tag, for which I feel very dirty indeed!)

Nearly all of the credit for the CSS goes to the excellent YUI Grids CSS library that Rob Knight clued me into via Twitter last week when I was battling with altering the K2 theme on Singularity to make it into a cross-browser three-column fluid layout.

(The scale9-esque fluid download cell is courtesy of the even more rounded corners with CSS technique.)

The HTML content is structured using several Django templates, which are supported by Google's webapp framework.

Finally, the Flash client uses the TabBar component from the open source Yahoo Astra Flash components and Uza's AS3 Global Object to implement several global convenience properties (like the current SWF's URL).

Getting Started

Getting started with The GAE SWF Project couldn't be easier.

1. Download and unzip

First off, download the Google App Engine SDK (includes the local Development Web Server and webapp framework.)

Next, download the latest release of the The GAE SWF Project and unzip it.

(Or, you can check out the unstable, bleeding-edge version from The GAE SWF Project Subversion repository's trunk on OSFlash.)

2. Start the server

Open up Terminal and navigate to the folder you unzipped The GAE SWF Project to. To start the Development Web Server type:

./start

This is a convenience script that I made that starts the Development Web Server and sets the mail server as localhost:5000. You can change these in the script of just use dev_appserver.py . to start it up without mail support.

If you want to monitor the email that gets sent, open up a separate Terminal window and, in The GAE SWF Project folder, type:

./monitor_mail

3. View the app and start hacking!

Now that the app is running, view it in the browser by hitting http://localhost:8080.

You can now open up the source folder and start exploring!

Trace you, trace me, trace it for always...

Wow, did I just paraphrase Lionel Richie?

Anyway, I find it useful to tail the Flash trace log (especially to see trace results in the browser and online). Here's how you do it:

Before you start, you need to enable logging by creating a file called mm.cfg in /Library/Application Support/Macromedia.

In it, enter:

ErrorReportingEnable=1
TraceOutputFileEnable=1

You only need to do this once. After that, whenever you want to tail the log, open up a new Terminal window and type the following, replacing USER with your home folder:

tail -f /Users/USER/Library/Preferences/Macromedia/Flash\ Player/Logs/flashlog.txt

Play, enjoy, share, have fun!

As I state on The GAE SWF Project site, I hope that this open source effort will help you to get started quickly with building Flash and Flex application on Google App Engine. In the past few days, I have had more fun developing this than I can remember in a long while. I love Python, I love Django, I love Google App Engine, and I love Flash and Flex. To have them all together... well, that's a dream toolset, right there!

And, there's something to be said about writing your app and then letting Google handle the rest. Personally, I can live with that.

(Oh yes, and I do desperately need to talk to someone at Google about hosting the Singularity conference web application on Google App Engine with regards to the quotas -- if you know whom I should contact, please either let me know directly at aral {at} aralbalkan(.)com or leave a comment below -- thanks!)

The GAE SWF Project is currently a proof-of-concept; it's a three-day old baby that I hope will blossom into a useful resource.

I hope you you enjoy it and I hope that it makes your life a little easier or at least gives you food for thought.

Play with it and let me know what you think in the comments.

Killing zombie sequences dead in KitchenSyncLib

I've only recently discovered KitchenSyncLib, an excellent open source ActionScript 3 library for sequencing all manner of things in Flash and Flex applications (animations, function calls, etc.)

It's an absolute joy to work with but I did hit one tiny snag: When you create a Sequence instance (or any subclass of AbstractSynchronizedActionGroup), populate it with some Actions, and then kill() it, the child actions do not get killed off and can cause the whole Sequence instance to return as a zombie to eat your brains as you tear your hair out in frustration (see issue 10).

The fix, thankfully, is easy. Just replace the kill() method in AbstractSynchronizedActionGroup with the one below:

override public function kill():void
{
	for (var i in _childActions)
	{
		_childActions[i].kill();
	}
	_childActions = null;
	super.kill();
}

Once you've killed all the children and performed your super.kill() power move, the zombie sequences will leave your brains alone forever. :)

Building Flash applications with Google App Engine

Update: This post is barely a week old and already outdates. See my updated post and The GAE SWF Project to get started quickly buildingFlash and Flex applications on Google App Engine.
Continue reading 'Building Flash applications with Google App Engine'

Better form validation in Flex

Flex comes with a built-in form validation system that unfortunately uses mystery meat tooltips to display component validation errors.

To see what I mean, take a look at the example I wrote a while back in the Validating Data Quick Start.

Mystery Meat Error Messages

If you tab around that example, you may notice that you are probably doing something wrong (as indicated by the red borders around the form items that begin to appear) but you have no idea what you're doing wrong. In order to find out, you have to mouse over the form field. Only then does a tooltip appear to tell you what the problem is.

Needless to say, having the user switch input devices and exert additional effort in order to see a form validation error does not make for good ergonomics or usability.

A better alternative is to actually display the error message beside the control.

You can, of course, do this simply by having the error message in a label.

For example:

<mx:FormItem label="Your name">
    <mx:HBox>
        <mx:TextInput id="yourName" change="validateNotEmptyTextInput(yourName);" focusOut="validateNotEmptyTextInput(yourName);"/>
        <mx:Label id="yourNameError" visible="false" text="Your name cannot be empty."/>
    </mx:HBox>
</mx:FormItem>

The validateNotEmptyTextInput() method, in this example, is not a Flex Validator (as used in my Validation Quick Start), but a simple method.

For example:

private function validateNotEmptyTextInput(target:TextInput):void
{
    (this[target.name+"Error"] as Label).visible = (target.text == "");
}

In the above example, I'm using a pragmatic naming convention to create a generic validation method that works with TextInput components. Nothing too spectacular visually, but usability-wise already better than the default Flex behavior.

Creating an error Label for each component, though, is not very practical. We can overcome this limitation and add a little visual flare by using the Flex error tooltip instead of a label.

Kyle Quevillon has a post in which he details how to use the Flex Tooltip Manager to create Error Tooltips. Referring to Kyle's post, we can alter the validateNotEmptyTextInput() method as follows:

// If the TextInput is empty, display an error message.
if (target.text == "")
{
    // Has the error message ToolTip already been created?
    // (A reference to created ToolTip instances is saved in a hash called errorMessageToolTips.)
    var toolTipExists:Boolean = errorMessageToolTips.hasOwnProperty(target.name);
 
    if (toolTipExists)
    {
        // Error message ToolTip has already been created, just show it.
        (errorMessages[target.name] as ToolTip).visible = true;
    }
    else
    {
        // Create the ToolTip instance.
        var pt:Point = new Point(target.x, target.y);
        pt = target.contentToGlobal(pt);
        var errorTip:ToolTip = ToolTipManager.createToolTip(errorMessages[target.name] + " cannot be empty", pt.x + target.width + 5, pt.y) as ToolTip;
        errorTip.setStyle("styleName", "errorTip");
 
        // Save a reference to the error message ToolTip in a hash for later use.
        errorMessages[target.name] = errorTip;
    }
}
else
{
    // TextInput is valid. Hide the error message if one exists.
    if (toolTipExists)
    {
        (errorMessageToolTips[target.name] as ToolTip).visible = false;
    }
}
 

Where errorMessages is a hash of personalized messages:

errorMessages =
{
    yourName: "Your name",
    yourEmail: "Your email",
    phone: "The phone number"
}

Thus, we no longer need the Label component but there is a catch: we still need the HBox (or a container of some sort) if the TextInput is in a FormItem. Otherwise, contentToGlobal() returns an incorrect value when trying to position the error message.

So the new FormItem looks something like this:

<mx:FormItem label="Your name">
    <mx:HBox>
        <mx:TextInput id="yourName" change="validateNotEmptyTextInput(yourName);" focusOut="validateNotEmptyTextInput(yourName);"/>
    </mx:HBox>
</mx:FormItem>

And the resulting validation errors both look nice and are functional.

Better Flex Validation Errors

(In the above example, I modified the errorTip style to make the message boxes slightly shorter than usual by setting the paddingTop and paddingBottom properties to 2.)

To summarize, I'm not a big fan of the mystery meat validation error tooltips in Flex. Displaying validation errors on the form itself leads to better usability as users do not have to exert additional effort to find out what they did incorrectly.

Update: Someone has filed a bug about this very issue in the public Flex Bug and Issue Management System. I've left a comment on the bug and linked it to this post.

Redispatching a ResultEvent with the AS3 Lightweight Remoting Framework

If you want to redispatch a ResultEvent when using Danny Patterson's AS3 Lightweight Remoting Framework, you have to modify the ResultEvent class to override the clone() method.

So, if you want to do something like this:

private function resultHandler(event:ResultEvent):void
{
    dispatchEvent(event);
}

Just add the following method to com.dannypatterson.remoting.ResultEvent:

public override function clone():Event
{
   return new ResultEvent(type, bubbles, cancelable, result);
}

Ditto for the FaultEvent.

SWX PHP AVM2/Flash 9: Status update

I know a lot of your are anxiously awaiting the AVM2/Flash 9 version of SWX PHP so you can start using SWX RPC in your ActionScript 3 and Flex 2/3 projects. I want to update you on where we are on that front.

I'm excited to announce that we have three excellent developers who are currently involved in writing the Flash 9 assembler for SWX and I'd like to introduce you to them.

Richard Lord is an ActionScript, PHP, and all-things-binary guru who by day creates cool Flash games with his company Big Room in London. I met Richard at Flash on the Beach this year and he graciously agreed to help out with the project. Richard's just completed some of the key methods on the SWX 9 assembler and his code is going to make it _much_ easier for us to move on with the rest of it.

Also on the project are two of our newest members, Chris Sperry and Tom Kennett from FlexibleFactory here in Brighton. This uber-geek duo are known as the Flash A-Team here -- because if you have a Flash problem that no one else can solve... well, you get the idea. In their spare time they do things like port Sinclair Spectrum emulators to Flash. And now, they're on board with the Flash 9 version of SWX. Yay!

So things have kicked off and we're working on it. I'll update you guys again when we have more to share.

What is SWX, how does it work, and where is it going?

I do some of my best thinking (and singing) in the shower. So it's no surprise that this morning, while in the shower, I decided to review my plans and roadmap for SWX. Here's a direct-from-the-shower look at what SWX is, how it works (with a few examples to get you up and running), and roadmap of where SWX is heading.

Some of the contents of this post will be familiar to my friends at Yahoo! UK, where I presented SWX earlier this month. (Thank you guys for your amazing support, it means a lot!)

Definitions

Let's start at the beginning with some definitions. When I first embarked on SWX, the technology and implementation were one and the same. Several months on, SWX has matured and simply bundling everything in the SWX ecosystem as "SWX" is not sufficient. To that end, here are some definitions of SWX-related concepts to start us off with a common vocabulary for talking about SWX.

  • SWX: Native data format for Flash. It is a subset of the SWF format. SWX SWFs are regular SWF files that are used to store just data.
  • SWX RPC: RPC protocol encoded in SWX. Allows you to call methods on server-side classes and get the results in SWX format.
  • SWX PHP: SWX RPC implementation in PHP. SWX PHP is currently the only implementation of SWX RPC but there will be Python, Ruby, J2EE, .Net, etc. implementations in the future.
  • SWX Tools: The SWX Service Explorer & SWX Data Analyzer. These tools come bundled with SWX PHP and will work with any future implementations of SWX RPC.
  • SWX AS: A high-level ActionScript library that handles 
the client-side queuing and execution of SWX RPC calls. You don't have to use the ActionScript library to work with SWX RPC as SWX is native to Flash but the library does provide you with useful functionality such as cross-domain access, queueing of data calls, etc.
  • SWX APIs: APIs for Flickr, Twitter, etc. I am as excited about the SWX APIs as I am about the SWX data format and SWX RPC as they provide Flash developers with a very easy way to create mashups. In fact, if you hit the Public SWX RPC gateway (see below) at swxformat.org, you can use these APIs with ActionScript alone (no server-side programming is necessary.)
  • Public SWX RPC gateway: Open SWX RPC endpoint. The Public SWX RPC Gateway
is at http://swxformat.org/php/swx.php. You can use the public SWX
APIs from this gateway in your own applications without having to
write any server-side code whatsoever.

Supported platforms and technologies

Swx Supported Platforms

You can create and load SWX SWF files with any version of Flash (5+) as they are simply SWF files. As far as manually creating SWX files go, SWX is supported on Flash 5+.

SWX PHP, the current SWX RPC implementation that I'm working on, creates SWX files that are compatible with Flash 7+ Flash 6+, Flash Lite 2.0 and Flash Lite 2.1. Currently, SWX PHP does not support Flash 9/AVM2 but it will eventually do so.

SWX AS, the SWX ActionScript library, compiles on Flash 7+ Flash 6+ and MTASC.

You can use SWX PHP currently to create applications that run on mobile phones (Flash Lite 2.0/2.1), the Nintenso Wii, Sony PS3, and devices like the Nokia N800 internet tablet and the Chumby.

You can also wrap SWX-based applications to create desktop versions using Adobe Air.

SWX (SWF Data Format)

SWX is the native data format for Flash. Data is stored as SWF bytecode (you can't get more native than that on the Flash Platform) that is interpreted by the Flash Player. The SWX format is a subset of the SWF format (just like JSON is a subset of JavaScript).

SWX is open. I am in the process of writing an Internet Draft (I-D) for SWX which I hope will become an informational RFC.

You loadMovie() SWX data files and they are ready to use the moment they are loaded. You don't need to deserialize or massage the data in any way before using it as it is stored in native Flash objects.

Why do we need a new data format?

When I first announced SWX, Patrick Mineault questioned whether SWX was reinventing the wheel. Why, he asked, do we need SWX when there is AMFPHP? (AMFPHP is a PHP implementation of a Flash Remoting gateway).

To start with, comparing SWX and AMFPHP is like comparing apples and oranges. As I stated earlier, SWX is a new data format for Flash and SWX RPC is a remote procedure call protocol encoded in SWX. As such, we can compare SWX to AMF (the data format) and SWX RCP to Flash Remoting (the RPC protocol) and SWX PHP (my PHP implementation of SWX RPC) to AMF PHP.

So the real question becomes, does the Flash Platform need a new data format and a new RPC protocol? I believe it does and here are some reasons why:

  • Existing formats are non-native, complicated, require parsing and/or writing plumbing code e.g., XML, variable-encoded strings (LoadVars, loadVariables), Flash Remoting, etc.
  • SWX files have low processor overhead when parsed by the Flash Player as they are native (SWF bytecode)
  • SWX RPC is the only RPC solution for Flash Lite 2.0 and 2.1 (and thus for mobile Flash applications). Flash Remoting does not work with Flash Lite.
  • Most important: SWX, being native, has inherent advantages such as cross-platform data exchange (via allowDomain support for SWF files), simplicity (no ActionScript library is necessary to use it), etc.

It's my first belief that every platform can benefit from a native data format that does not require parsing. The main advantage of SWX over other data formats and of SWX RPC over other RPC solutions is ease of use. I hope that this ease of use will spur a wealth of development of data-driven applications and mashups on the Flash Platform by developers who may traditionally have shied away from creating such applications because it was just too darn hard to do so.

SWX RPC

SWX RPC is a remote procedure call protocol encoded in SWX format. You use it to call methods on server-side classes (called services in SWX RPC) and get the results returned to you in SWX format.

SWX RPC is open. I am in the process of writing an Internet Draft (I-D) for SWX RPC which I hope will become an informational RFC.

SWX RCP is stateless, lightweight, and uses HTTP as the transfer protocol.

A typical SWX RPC call involves parameters sent from Flash to the SWX RPC endpoint (gateway) in JSON format. These consist of serviceClass, method, and args parameters that define the method on the service class that you want to call on the back-end and the arguments that you want to send to that method. The resulting data is returned to Flash in the result property.

SWX PHP

SWX PHP is a SWX RPC implementation in PHP. It is open source.

SWX PHP is written in pure PHP. It doesn't require any extensions and runs under both PHP 4 and 5. (As such, it runs without problems even on shared hosting accounts.)

SWX PHP has a SWX RPC endpoint (gateway) and an assembler that creates and returns SWX files. Your service classes contain business logic only.

SWX PHP comes with service classes (APIs) for Flickr, Twitter, Ten Word Review, Nabaztag, etc. There is a publicly accessible instance of SWX PHP running on swxformat.org at http://swxformat.org/php/swx.php. You can access these APIs from this public gateway without hosting your own instance of SWX PHP if you want to build mashups using just these APIs.

SWX PHP uses Amfphp as a library and this means that you can also hit SWX PHP services via Flash Remoting, JSON and XML-RPC. (In other words, you're not locked into using SWX RPC and you can switch easily between these various technologies if you want to.)

SWX PHP comes with a plain vanilla installer (unzip it into your web folder on the server and go) and as a MAMP Bundle (everything you need to get up and running with SWX PHP on OS X). I am planning on creating Windows and Linux bundles as well in the future. In the meanwhile, I recommend using WAMP on Windows and XAMMP on Linux is you want to quickly get up and running with a server (Apache + PHP, etc.) on your development machine.

SWX PHP adheres to SWX’s core philosophy of Systemwide Simplicity.

Systemwide simplicity

A system is only as simple as its most complicated part. It's not enough to just simplify individual components and processes, you must also simplify the relationships and interactions between components and sub-processes. Systemwide Simplicity takes a wider approach to simplicity that involves understanding and supporting the entire user experience.

It is thus my aim to make it as easy as humanly possible for Flash developers to start creating data-driven Flash applications from the moment they arrive on the SWX homepage to the moment they first get data into Flash using SWX RPC.

How simple is SWX? Moo card example

SWX is so simple that instructions for getting data into Flash using it easily fit on to a Moo card. (In fact, I've just ordered two sets of Moo cards with just this example on them -- ask me for one if you see me around!)

To get a list of the most recent 100 photos from Flickr into Flash, do the following:

  • Open up the SWX Data Analyzer
  • In Flash, create a new FLA and create a movie clip on the Stage. Give it the instance name loader.
  • Write the following code on to the frame that the loader movie clip is on:
loader.serviceClass = "Flickr";
loader.method = "swxPhotosGetRecent";
loader.debug = true;
 
loader.loadMovie("http://swxformat.org/php/swx.php", "GET");

That’s it! Test your movie and look in the SWX Data Analyzer to see the results being loaded in to Flash from Flickr. That’s how simple SWX is.

If you want to display the results from within Flash, create a long, single-line dynamic text field on stage and give it the instance name status. Add the following code to the timeline:

function onEnterFrame()
{
    status.text = loader.result.photo[0].src;
}

Initially, the status text field will display undefined until the data is loaded and then it will display the URL of the first photo from the list of recent photos that is loaded from Flickr. Notice how you can access the results as native Flash objects the moment they’re loaded. No deserialization or massaging of the data is necessary!

Read the next section to see a better way of handing results using SWX AS and the SWX Class in ActionScript.

Building a complete web application (back-end and front-end) with SWX PHP

In the next ten minutes you are going to learn everything there is to know about exactly how SWX PHP works by building a very simple, but complete, data-driven Flash application. You will be using Flash to create the client and PHP (with SWX) for the server.

Installing SWX PHP

If you haven’t done so already, download and install SWX PHP on to your computer. Before installing SWX PHP, you will need to have a web server running PHP on the machine you’re installing it on.

If you’re on a Mac, running OS X, download and install the SWX PHP MAMP Bundle. This will have you up and running with everything you need using a simple installer.

If you’re on Windows, I suggest installing WAMP and, on Linux, XAMMP. Both of these are single-click installers that provide you with a turnkey development environment with a web server (Apache) and PHP.

Once you’ve installed a web server and PHP, just download SWX PHP and unzip it into your web root. Start your web server and hit the web root in your browser to access the SWX PHP Start Page.

Swxphp Start Page


Getting Started

The application you’re going to build is a simple calculator that uses a server-side method to add two numbers together.

To start, you're going to create a PHP service class. In SWX you place service classes under the php/services folder.

SWX Service Explorer

To see what services are already in the services folder, you can use the SWX Service Explorer that comes with SWX PHP. Open that now and you will see that there are several services there already.

Swx Service Explorer

Creating the Calculator service class in PHP

Create a new file using your text editor of choice under php/services/ and call it Calculator.php.

Add the following code to Calculator.php and save the file:

 
&lt;?php
    class Calculator
    {
        function addNumbers($n1, $n2)
        {
            return $n1 + $n2;
        }
    }
?&gt;

This is a very simple server-side service class that has a single method called addNumbers(). This method takes two numbers as arguments and returns their sum.

At this point, it would be nice if you could test the server-side method you just created without having to create a Flash client. SWX Service Explorer lets you do just that.
Testing server-side methods with the SWX Service Explorer

Return to the SWX Service Explorer (or open it if you didn't earlier) and you will see the Calculator class you just created. Click on it and you will see the addNumbers() method that you just created. Enter two numbers in the $n1 and $n2 fields and press the call button to test out the method. You should see the sum returned in the results area.

Your server-side service method is working correctly. Now let’s call it from Flash.

  1. Open up Flash and create a new FLA (ActionScript 2). You can set the publish setting to Flash 7 or 8.
  2. On Frame 1 of the new FLA, create a movie clip instance and give it the instance name dataHolder.
  3. Create a new layer and call it Actions. On the Actions layer, add the following code:
dataHolder.serviceClass = "Calculator";
dataHolder.method = "addNumbers";
dataHolder.args = "[35, 7]";
dataHolder.debug = true;
 
dataHolder.loadMovie("http://localhost:8888/php/swx.php", "GET");

That's it! That's all the code you need to call the addNumbers method on the Calculator service class in PHP and pass it the numbers 35 and 7 as arguments. The loadMovie calls the SWX gateway and passes to it any of the properties you set on your movie clip. In this case, since we are sending a small number of arguments, we use the GET HTTP encoding method. We could just as easily have used POST.

SWX Data Analyzer

Before testing the movie, open the SWX Data Analyzer in a separate browser window.

Swx Data Analyzer

SWX Data Analyzer is a debugging tool that shows you the SWX data that arrives inside your Flash movie.

To make SWX data that loads into the Flash player appear in Analyzer, you turn debug mode on. That's what the line dataHolder.debug = true does.

Now, test your movie and then look in the Analyzer. If all went well, you should see the number 42.

Accessing the result property

That's great, but now let's display that result in Flash. You're going to implement a quick hack to get it working and we can evolve the application later to improve it.

Add a TextField instance to the Stage and give it the instance name status.

Next, create an onEnterFrame handler that prints out the value of the result property of the dataHolder movie clip into the status text field.

The complete script at this point is shown below:

dataHolder.serviceClass = "Calculator";
dataHolder.method = "addNumbers";
dataHolder.args = "[35, 7]";
dataHolder.debug = true;
 
dataHolder.loadMovie("http://localhost:8888/php/swx.php", "GET");
 
<strong>function onEnterFrame()
{
    status.text = dataHolder.result;
}</strong>

Test the movie and you should see the number 42 appear in the status text field.

Now stop for a moment and take a deep breath: You now know exactly how SWX RPC works!

You didn't import any classes, you aren't using an API, you didn't include any external code whatsoever. SWX is completely native to the Flash platform and, if you want to, you can make use of it by using only built-in Flash features like you did here.

Compare this to other technologies like Flash Remoting. Do you actually know exactly how Flash Remoting works? There are numerous classes, lots of code, etc. There's some magic involved that you don't really understand. Not so with SWX RPC. With SWX RPC, your data arrives in native Flash format.

It's important for a technology to be so simple that you can actually conceptualize it completely. However, that doesn't mean that the above method is the way you'd want to use SWX PHP on a daily basis.

For one thing, take a look at how you set the arguments. It's a string. In fact, what you did was serialize the arguments you're sending in JSON format. It's not confusing or difficult to this by hand if you are sending simple arguments like two numbers but what if you wanted to send an array of complex objects over? It would get tiresome and impractical very quickly.

The example you just created uses the No API method. In other words, you used pure Flash. No additional classes.

However, to make your life easier, you may want to use just a little API. Specifically, a method to serialize your arguments into JSON format for you would be nice. The SWX AS minimal API provides just such a method. Modify the code sample so that it matches the listing below:

<strong>import org.swxformat.SWX;</strong>
 
dataHolder.serviceClass = "Calculator";
dataHolder.method = "addNumbers";
dataHolder.args = <strong>[35, 7]</strong>;
dataHolder.debug = true;
 
<strong>SWX.prepare(dataHolder);</strong>
 
dataHolder.loadMovie("http://localhost:8888/php/swx.php", "GET");
 
function onEnterFrame()
{
    status.text = dataHolder.result;
}

Notice the lines that have been added and the line that had changed (in boldface). The prepare() static method of the SWX class simply serializes your arguments into JSON format for you. Notice that the args property in your dataHolder is no longer a string but an ActionScript array with two numbers inside it.

This is definitely far better than manually serializing your arguments by hand but it's still not ideal, is it? For one thing, that onEnterFrame function we're using is not a good practice. It would be really nice if we could have an event handler called when the data arrives instead of polling for it. The SWX AS Full API provides that functionality (and a few more).

Modify the code listing so that it matches the one below:

import org.swxformat.SWX;
 
<strong>var swx:SWX = new SWX();
swx.gateway = "http://localhost:8888/php/swx.php";
swx.encoding = "GET";
swx.debug = true;
 
var callParameters:Object =
{
    serviceClass: "Calculator",
    method: "addNumbers",
    args: [35, 7],
    result: [this, resultHandler]
}
 
swx.call(callParameters);
 
function resultHandler(event:Object)
{
    status.text = event.result;
}</strong>

When you run the above example, you should again see 42 in the status text field. Let's look at what has changed.

When using the SWX AS Full API, you actually instantiate the SWX class and set some properties there (such as the gateway URL, encoding method and whether you want debug information for calls).

Instead of putting call-related parameters directly into a movie clip (you can delete the dataHolder movie clip now as you aren't using it any more), you create a callParameters object and specify the serviceClass, method, and args properties there. But you can do more, you can also specify a result handler that will get called once the data has loaded.

The result handler receives an event object as an argument. That event object has a result property that points to the loaded data.

The SWX AS Full API doesn't stop there. You can also specify a timeout handler to handle calls that take too long.

Modify the listing so that it matches the one below:

import org.swxformat.SWX;
 
var swx:SWX = new SWX();
swx.gateway = "http://localhost:8888/php/swx.php";
swx.encoding = "GET";
swx.debug = true;
<strong>swx.timeout = 2;</strong> // seconds
 
var callParameters:Object =
{
    serviceClass: "Calculator",
    method: "addNumbers",
    args: [35, 7],
    result: [this, resultHandler],
    <strong>timeout: [this, timeoutHandler]</strong>
}
 
swx.call(callParameters);
 
function resultHandler(event:Object)
{
    status.text = event.result;
}
 
<strong>function timeoutHandler()
{
    status.text = "Call timed out!";
}</strong>
 

The default timeout duration is 30 seconds but you can override that, as shown here.

In order to make the call actually time out, modify the Calculator class in PHP too to make it sleep for 10 seconds before returning the result. The Calculator class should match the one in the listing below:

&lt;?php
class Calculator
{
    function addNumbers($n1, $n2)
    {
        <strong>sleep(10);</strong> // Make the call time out!
        return $n1 + $n2;
    }
}
?&gt;

Now test your Flash movie and, after two seconds, you should see the SWX call time out. Timed-out calls are cancelled and will not trigger the result handler at any point in the future.

Finally, there is also a fault handler that you can use in the same way. To test it out, modify the ActionScript listing so that it matches the one below:

import org.swxformat.SWX;
 
var swx:SWX = new SWX();
swx.gateway = "http://localhost:8888/php/swx.php";
swx.encoding = "GET";
swx.debug = true;
swx.timeout = 2; // seconds
 
var callParameters:Object =
{
    serviceClass: "Calculator",
    method: "addNumbers",
    args: [35, 7],
    result: [this, resultHandler],
    timeout: [this, timeoutHandler],
    <strong>fault: [this, faultHandler]</strong>
}
 
swx.call(callParameters);
 
function resultHandler(event:Object)
{
    status.text = event.result;
}
 
function timeoutHandler()
{
    status.text = "Call timed out!";
}
 
<strong>function faultHandler(event:Object)
{
    status.text = event.fault.message;
}</strong>

And modify your class so that it generates an error:

&lt;?php
    class Calculator
    {
        function addNumbers($n1, $n2)
        {
            <strong>return $n3;</strong> // $n3 does not exist!
        }
    }
?>&gt;

Test your FLA and you should get something along the lines of Error 8: Undefined variable: n3 in /htdocs/swx/trunk/php/services/Calculator.php, line 7 in the status text field in Flash.

The fault handler also returns API-specific fault codes (e.g., Flickr API error codes) back to Flash.

And that, in a nutshell, is the SWX AS Full API.

There's more to SWX that we haven't covered in this introductory article such as the LoadManager and ExternalAsset classes that the SWX AS Full API uses internally to queue and load SWX SWFs but you can find out more information about these in more advanced tutorials to be released soon (they are useful when you want to load your own external assets like SWFs, JPGs, etc.)

Beyond making your own service classes, you can also use the existing service classes in SWX to access public APIs like the Twitter API and Flickr API. In fact, why don’t you play around with the Twitter and Flickr APIs now, using the PHP Service Browser to discover how they work? You can modify the examples above to get data from any of those APIs as easily as you have done here.

There is also a screencast of this example that you can watch online.

SWX and Flash Lite (mobile applications)

SWX and SWX RPC work in Flash Lite 2.0 and 2.1! In fact, due to its low processor overhead and native support in Flash, SWX is the ideal data format for mobile applications with Flash Lite.

Check out the MiniFlickr sample application that comes with SWX PHP for an example of how to build data-driven Flash Lite applications using SWX.

Keep in mind that, due to a bug in Flash Lite, you cannot make POST requests in a loadMovie call. Instead, you must make GET requests when using SWX RPC with Flash Lite. For more information on this, see the Mobile Limitations section, below.

The MiniFlickr application makes use of the ExternalAsset and LoadManager classes that come with SWX AS to queue all load requests (data and assets such as images). This is essential in mobile development as most handsets will fail if you try to load two things at once. The SWX AS Full API handles the queueing of requests for you and gives you a general purpose load queue that you can use in your own applications. Make sure you study the MiniFlickr sample if you want to create Flash Lite applications using SWX PHP.

Swx Mobile Device Central

SWX and SWX RPC advantages for mobile development

SWX RPC is the only RPC solution for Flash Lite and, beyond that, it works really well and is simple to use. Here is a summary of some of the advantages of the SWX data format and SWX RPC for Flash Lite development:

  • Native; data is ready to use the moment it loads as native ActionScript objects.
  • No processor-intensive parsing, etc.
  • No plumbing code for deserializing requests.
  • Public gateway and APIs for mobile mashups.
  • Only RPC solution for Flash Lite.
  • Easy to understand and use.

SWX Flickr API

As of the upcoming SWX PHP Release Candidate 1, a full implementation of the Flickr API is included in SWX PHP.

You can start playing with the SWX Flickr API right now, using the Public SWX RPC gateway. Try the methods out online using the SWX Service Explorer.

  • Implements the full Flickr API, current as of August 1, 2007.
  • Liberal open source license (MIT).
  • Provides photo upload feature.
  • Actively maintained and updated.
  • Simplest way for Flash developers to work with Flickr.

Roadmap

So where is SWX, SWX RPC, and SWX PHP going?

I realized today that I was being overly ambitious with my plans for version 1 of SWX PHP.

For one thing, I had considered getting the Flash 9/AVM2 version of SWX PHP ready in time for version 1 but that involves writing a whole new assembler. I've now decided to leave this for after the 1.0 release so that I can instead concentrate on getting a polished and stable 1.0 release of SWX PHP that includes all the learning materials, screencasts, etc. that you need to get up and running with SWX RPC.

SWX PHP already fills a gaping void in RPC solutions for Flash Lite and getting SWX PHP to version 1.0 is important in getting development houses to adopt SWX PHP for production of Flash Lite applications.

Also, the SWX assembler (the bit that creates the SWX SWF files) in SWX PHP is extremely stable and has been for a while and I want the Flash 9/AVM2 version of it to be as stable when it goes into version 1 but that's not realistically going to happen in the timeframe that I have in mind.

So, instead of working on yet another implementation, I'm going to spend the next few weeks working on the Internet Drafts for SWX and SWX RPC and on documenting the heck out of SWX so that others can create implementations of SWX RPC (in fact, if anyone is interested in undertaking the Flash 9/AVM2 implementation for PHP, please get in touch).

What is important is that eventual Ruby, Python, J2EE, .Net, etc. implementations of SWX RPC are all compatible and that they all adhere to the same philosophy of simplicity. (And thus, for example, do not require extensions, etc. or place other barriers in front of developers.)

So what is the eventual release data of SWX PHP? I'm going to be aiming for the start of September and definitely before FlashForward Boston.

I will be releasing Release Candidate 1 of SWX PHP this week so keep any eye out for that on this blog.

Also expect a number of new screencasts in the coming days, showing you how to work with SWX PHP and the various APIs and how to create mobile applications using SWX PHP.

Come September, I will be embarking on a crazy schedule of conferences, starting with FlashForward Boston to present my session Let's talk about SWX, baby!

The conferences I'll be presenting SWX at include MAX Chicago, FlashForum Conference (Germany), MAX Barcelona, FITC Hollywood, Flash on the Beach (Brighton, UK), and MAX Japan.

I hope I'll get to meet and talk with some of you at these conferences. If you see me, do come up and say hello and ask me for a SWX Moo card and a SWX Moo sticker :)

Flash CS3 Components

Notes from Grant's talk on the new Flash CS3 Components at FITC 2007.

Core philosophy: Build a component set targeted at rich experience creators.

Main objectives

  • Size and performance: Reduce file size for downloads and minimuze CPU/memory impact
  • Easy skinning & stlying: Simplify the workflow for customizing the appearance of components
  • Extensibility: Make the architecture more approachable to encourage customization
  • Knowledge portability: Ensure user knowledge can be transferred from the Version 2 components and Flex.

Size and performance

Size:

  • Reduced size vs. v2 by 25-40% (depending on components used)
  • Base size: ~10kb smaller than v2 (27KB vs. 17KB). ~110kb smaller than Flex 2.

Performance

  • Lower CPU, higher capacity.
  • Inherent AS3 performance gains.
  • Also took advantage of new features: event model, strong typing, Dictionary.
  • No more recursive lookups.

He's showing a demo of a List component with 1,000,000 items in the list and it's scrolling smoothly. He selects 100,000 items and it's almost instantaneous.

Skinning and styling: simplicity and power

Visual skinning

Process:

  1. Drop component on stage.
  2. Double-click component.
  3. Edit assets.
  4. Rinse, repeat.

Tip: You can use graphic symbols with Scale-9 for sharing component assets.

Limitation: No author-time preview

Everything is visually editable.

You can also use programmatic skinning if you want to.

Process:

  • Option 1: Bind a class to the skin clip
  • Option 2: Write timeline code on the skin clip

You just need to expose the width and height setters.

Stlying:

Styling lets you apply skins, text formats, and other style settings to instances, all components, or all components of a certain type.

Usage:

import fl.managers.StyleManager;
 
// Change a style on a single instance
myInstance.setStyle("styleName", styleValue);
 
// Change a style for all components
StyleManager.setStyle("styleName", styleValue);
 
// Change a style for instances of a specific component
StyleManager.setComponentStyle(component, "styleName", styleValue);

Styling no longer causes an inefficient recursive look-up system. So you can style at runtime without a performance hit.

Instances as skins:

Advanced feature. You can now use an instance as a component's skin.

Demo: Using a dynamically loaded asset as an icon skin. Grant loads a semi-transparent PNG using a Loader and sets it as the icon for a button.

Demo: Using instance skins to programmatically skin a slide. This rocks: Grant passes a Sprite instance as the track skin for a slider and updates the gradient fill in it at runtime.

Note: Only a single component instance can use an instance as a skin.

Lists: TileList, DataProvider and CellRenderer

TileList: New list type.

DataProviders

No longer obscured as an Array mix-in. Mandatory for use with lists. Sync multiple lists using the same DP.

// data can be an Array, XML, etc.
myList.dataProvider = new DataProvider(data);

Methods: addItem, removeItem, replaceItem, merge, invalidate, sort, toArray, etc.

Events: DataChange and PreDataChange events show the type (add, remove, replace, sort) and the indexes/items affected.

CellRenderer

Extend the CellRenderer class to create your own custom cell renderer.

import fl.controls.listClasses.CellRenderer;
 
public class MyRenderer extends CellRenderer
{
	// ...
}

Or implement ICellRenderer: x, y, data, listData, selected, setSize, setMouseState.

Architecture: behind the scenes

Shallow, linear class hierarchy without mixins and a clear inheritance structure (limited use of composition). Makes use of protected members with few private or namespace-protected members. In short, you can extend pretty much anything. Uses consistent coding standards.

To create your own components, you extend UIComponent and can, if you want to, make use of the InvalidationType, ComponentEvent, StyleManager and FocusManager classes.

To create a custom list called MyList, for example, you would extend the SelectableList class, which extends BaseScrollPane, which extends UIComponent. Although the list classes are probably among the most complicated, the inheritance hierarchy is relatively shallow.

The framework allows for the granular invalidation of specific aspects of a component. e.g., foo.invalidate(InvalidationType.SIZE); All invalidated aspects of a component get redrawn at the next RenderEvent.

There is a registration-based style model where components register for specific styles. Supports style inheritance and pass-through styles.

The components support smooth scrolling (pixel level scrolling on all List-based components, as opposed to cell-level scrolling).

The framework has smart renderer reuse. Renderers are reused intelligently, leading to less flicker than in the Version 2 components.

The Bad

Although the components are a huge step forward when compared to the Version 2 components, Grant wants to point out some of their limitations. These include:

  • No databinding or data components. These features are apparently not commonly used in the the experience market.
  • No CSS (uses a simplified style model instead).
  • No tree or accordion components.
  • API variances (some component interfaces differ from those in Flex 2).

This was a hugely informative session and was very well presented.

SWX: A good idea

I just read that Patrick Mineault thinks that SWX is a bad idea. Although I have the utmost respect for Patrick and I love and support his work, I respectfully disagree with him. SWX is a good idea and here's why.

(I started responding to Patrick's post in the comments on his blog but it got too long so I'm posting it here instead.)

The followering are the main points Patrick makes in his post, along with my counter-points:

Now my first point is that SWX reinvents the wheel, and for no good reason. Let's list out the various ways to do asynchronous data communication in Flash. We have LoadVars, XML, Remoting, JSON, SOAP, XML-RPC, and PHPObject. One solution seems more than enough for this very simple tasks; adding another one to these 7 seems like a complete waste of time.

I remember when Flash Remoting came out that, for a long time, people would make the same argument against it: Why do we need another way to exchange data? Why did they re-invent the wheel? And the answer is the same now as it was then: We need it because the existing methods do not meet the needs of certain people.

If we were to accept Patrick's argument at face value, there would be no reason to go beyond LoadVars and we could throw XML, Remoting, JSON, SOAP, XML-RPC and PHPObject away, labeling all of them as redundant. After all, as I mentioned in my talk at the LFPUG last night, the core concept at the heart of building data-driven applications is a glorified form of automated copy and paste. We are moving information around from one place to another. In place of trucks, we use pipes to move our data. But it's transportation, not rocket science. So anything you can do with Remoting you can do with XML and LoadVars. Based on this argument, Remoting, XML, JSON, SOAP etc. all re-invent the wheel. But that's not true. Each has its specific strengths, weaknesses and use-cases. As does SWX.

Of course, it wouldn't be if in fact SWX gave some mighty good advantages over all the other solutions. To my knowledge, however, the only positive advantage to using SWX is the ability to use getBytesLoaded and getBytesTotal, which isn't available, in, say, Remoting.

SWX does have several mighty good advantages over all of the other solutions, above and beyond giving you the ability to display a determinate progress indicator as mentioned by Patrick. (If that was the only advantage, as much as I like determinate progress bars, I surely would not have invested as much time and effort into creating this as I have!) :)

Here are just a few advantages I can think of off the top of my head that SWX has over other methods:

  • It's simpler to use.
  • Data is deserialized twice only as opposed to four times.
  • You don't have to learn a new API and can reuse your existing knowledge.
  • It is useful in mobile applications with limited processing power
  • The final downloadable bundles of SWX will contain everything you need to get up and running (you don't need to buy or download additional tools).

I want to elaborate on some of the above points, starting with the advantage of having two deserialization steps instead of four. To illustrate the point, I'll use the model that Patrick presents in his article on Clearing the FUD on amfphp’s speed versus JSON and XML (which is quite ironic since I'm clearing the FUD about SWX here!) In it, Patrick accurately states the following:

In most any RPC model, there are the following steps:

  • Serialization of the request on the client-side
  • Uploading of the message to the server
  • Deserialization of the request on the server-side
  • Dispatching on the server-side
  • Serialization of the response on the server-side
  • Downloading of the message to the client
  • Deserialization of the message on the client-side

In most any RPC model, that is, except SWX. Let's look at how the above list looks in SWX.

Steps in SWX:

  • Serialization of the request on the client-side
  • Uploading of the message to the server
  • Deserialization of the request on the server-side
  • Dispatching on the server-side
  • Serialization of the response on the server-side (i.e., assembly of the SWX SWF)
  • Downloading of the message (i.e., SWF) to the client
  • Deserialization of the message on the client-side

Straight off the bat, we remove the deserialization of the request on the server as the PHON object that is sent over is evaled, following security checks. The big advantage, however, is that we also remove the deserialization step on the client side because your Flash client is receiving a native SWF. There is no deserialization. The moment the SWF is loaded, it is ready for you to use. Just access the data structure and you're off.

Among other things, this means that there's no equivalent of the Flash Remoting Mystery Time. Once the SWF is loaded, the data structure is immediately available for you to use. Any sort of deserialization on the Flash client is going to use up processor cycles and SWX, by design, is the least processor intensive method possible since it is SWF bytecode and that's as native as you get in Flash.

Of course, time will tell how SWX compares with the other options in terms of performance, etc. but my gut tells me that a fully optimized SWX will compare very favorably indeed. It is, of course, not fair to compare it on these grounds currently as we are at a very early alpha release (think: one step removed from a proof of concept) and it is currently not optimized in any way. Most importantly, though, SWX is not in a pissing contest with other formats. It is one alternative, it is simple, and it has very valid use cases. In fact, one of the first things I am planning to do is to show people how SWX can be used alongside Amfphp and the single-package distributions of SWX will actually include Amfphp (I love Amfphp, Patrick, you know that!)

If you look at the sample code on the webpage . . . The first thing you'll notice is that dataHolder is a movie clip on Stage. That means that either you must place this empty movie clip on stage manually, or you have to use createEmptyMovieClip first. Of course, if you do the latter, you have to think about depths and whatnot. The second thing you'll notice is that there is an onEnterFrame. I thought the whole reason we dropped the use of onEnterFrame for polling a movie clip is that we had all sorts of crazy issues with that, including the difference between 0 and 4 loaded bytes.

I think Patrick is missing the point here. The key thing here is that Flash developers understand movie clips and know how to work with them. That sample code is purposefully simplistic. Of course, I will be releasing utility classes that abstract that away from you if you want to use a highler level API but the important design consideration here is that you *don't* have to learn a new API to use SWX. That's the beauty of it. You can use your existing Flash knowledge to easily create data-driven applications. And for those of you who *want* to have a higher-level interface, you'll have one. But it won't be forced on you.

Also, there is nothing wrong with using an enterFrame handler. The initial states (negative, etc.) tell you the various states that the load process is in and are actually very valuable for presenting accurate status information (is it waiting for data, receiving it, etc.) And, of course, you *can* display a determinate progress bar when you start loading the data. Apart from the usability advantages of doing so, it's just plain cool! :)

The third point is that the PHON serialization that is used relies on a prototype hack . . . So we hack toString in Array, Object and even (gasp!) String. I am not even to bother to expand as to the myriad ways in which I think this is a bad approach, but you can imagine the argument.

Ah, I just knew that people would get stuck at this point :)

Just to make it perfectly clear: The PHON serialization in SWX does *not* rely on a prototype hack. The current alpha of SWX happens to contain the automatic PHON serializer as the only option. I just didn't have the time to also release an alternative utility class that doesn't rely on extending the prototype object.

As I mentioned in my talk at the London Flash Platform User Group yesterday, this automatic workflow is very cool but you would be right to have concerns about object pollution if you use this method. Whether or not this will be a problem depends on your application. For simple apps, it should be fine. But if you're uncomfortable with it (or if you're using the toString() methods of the Object, Array or String classes for other purposes in your application), then you won't have to use the automatic PHON serialization method and you can use a manual method instead. That will involve one extra line of code:

org.swxformat.PHP.serialize(dataHolder.data);

To say that PHON serialization in SWX *relies* on a prototype hack is incorrect. The automatic PHON serialization workflow happens to be the only one I had time to implement in time for the initial launch. The manual method will follow very shortly (in fact, I think I'll get it into the next release.)

The fourth issue with thi