Introducing the Swiz [URLMapping] Metadata Processor
Swiz 1.0 has introduced the ability to create your own custom metadata processors. Although the 1.0 release is fairly new, many custom processors have already been developed by members of the Flex community. I thought I'd take a stab at creating a metadata processor that simplifies adding deep linking support to your application.
The metadata processor I've created is called URLMapping which allows you to easily map URLs to methods. Here's a simple example:
[URLMapping( url="/helloWorld" )]
public function sayHelloWorld():void
{
model.msg = "Hello world!";
}
The URL Mapping processor will automatically start listening for URL changes. For the above example, any time the URL changes to flexapp.html#/helloWorld the sayHelloWorld() method will automatically get called. Also, since url is the default metadata argument, the following example works exactly the same:
[URLMapping( "/helloWorld" )]
public function sayHelloWorld():void
{
model.msg = "Hello world!";
}
You can also use parts of the URL as parameters:
[URLMapping( "/hello/{0}" )]
public function sayHello( name:String ):void
{
model.msg = "Hello " + name + "!";
}
And optionally change the browser window title when the URL changes:
[URLMapping( url="/hello/{0}", title="Hello {0}!" )]
public function sayHello( name:String ):void
{
model.msg = "Hello " + name + "!";
}
Lastly, [URLMapping] also works in reverse with the help of the Swiz [Mediate] metadata. In this example the URL will change to /hello/Ryan and the browser window title to "Hello Ryan!" when the HelloEvent.HELLO event is dispatched:
[URLMapping( url="/hello/{0}", title="Hello {0}!" )]
[Mediate( event="HelloEvent.HELLO", properties="name" )]
public function sayHello( name:String ):void
{
model.msg = "Hello " + name + "!";
}
And then dispatch the event:
<s:TextInput id="nameInput" text="Ryan" />
<s:Button label="Say Hello" click="dispatchEvent( new HelloEvent( HelloEvent.HELLO, nameInput.text ) )" />
[URLMapping] Getting Started Resources
I've created a simple Customer App example, with view source enabled, to show how you could use [URLMapping] in a full application.
Skinning MinimalComps with Degrafa
Just a quick post to show how you can utilize Degrafa and MXML to skin the MinimalComps components. Currently this adds just over 50kb to your SWF but it's on on going effort to lower this and minimize the dependencies on Flex classes.
My skin extends from GeometryGroup which instead of adding another DisplayObject to the display list it simply draws directly on the component.
I really like the idea of using AS3 for your component behavior/logic and seperating your views/skins using MXML. This is something Flex 4 is trying to achieve with FXG and it would be cool to see other frameworks do the same with Degrafa.
Using MXML without Flex (Example and Source)
I made a few minor changes to the MinimalComps project from Keith Peters and got it playing nicely with MXML. The below application compiles to a tiny 23KB yet makes use of MXML and even data binding.
I added only 2 new extra classes (Container and Application). Container simply adds the ability to add child DisplayObjects via MXML. Application extends Container and handles configuring the stage.
The only changes I made to the existing MinimalComps classes was adding a few metadata tags and modified VBox and HBox to extend Container.
View or download the full source code.
Here's the source for the main mxml file:
Note: This has nothing to do with the new framework we are building. I just wanted to show off how easy it is to use MXML without Flex.
Here’s 5 3D Layouts for Flex 4
I spent some time converting the OpenFlux 3D layouts to Flex 4 last week and have attached the example with source code. This includes CoverFlow (horizontal and vertical), Carousel, Spiral and Time Machine. I also included one which was created when I screwed up the CoverFlow layout but I thought it looked cool so I hit Save As and named it AwesomeLayout.
Overall I was really happy with how quickly I could get these working with Flex 4. It wasn't quite as painful as I originally thought and I'll discuss the differences below.
View the Example
View the Source Code
ILayoutElement
In Flex 4, UIComponent implements ILayoutElement which provides you a bunch of methods to manage the layout of each child. For 2D layouts you would use element.setLayoutBoundsSize( width, height, postLayoutTransform ) to set the size and element.setLayoutBoundsPosition( x, y, postLayoutTransform ) to set position.
OpenFlux instead allows you to set x, y, width, height, z, rotationX, rotationY, rotationZ directly to a token which is used to animate the child to its new position/size.
Matrix3D
With OpenFlux, you set the z, rotationX, rotationY, rotationZ properties directly. With Flex 4 you instead use element.setLayoutMatrix3D( matrix, postLayoutTransform ). Instead of passing in the above properties it instead expects an instance of Matrix3D. This was my first use of Matrix3D and Vector3D (FP10 classes) and had no idea what I was doing until I looked at the example Flex 4 WheelLayout
A common approach would be to first set the initial 3D coordinates of the child, next apply any rotation and third center the child in the container. Below is the Matrix3D code for AwesomeLayout:
var matrix:Matrix3D = new Matrix3D();
matrix.appendTranslation( elementWidth * -( selectedIndex - i ), elementHeight / 2, 0 );
matrix.appendRotation( Math.abs( selectedIndex - i ) * 2, Vector3D.Y_AXIS );
matrix.appendTranslation( width / 2, height / 2, 0 ); // center element in container
element.setLayoutMatrix3D( matrix, false );
maintainProjectionCenter
FP10 adds a perspectiveProjection property to the Transform class which works similar to a camera in Away3D. By default, the prespectiveProjection is set to the top left but for my layouts I need it to be the center of the container. This is easily done with the following code:
var pp:PerspectiveProjection = new PerspectiveProjection();
pp.projectionCenter = new Point(container.width / 2, container.height / 2);
container.transform.perspectiveProjection = pp;
Since wanting center projection is so common though, Flex 4 made this even easier by adding a maintainProjectionCenter flag to UIComponent. When the layout is attached to a container, I simply override the setter and set this property to true.
layer
Another pain in the butt with FP10 is that the z property has nothing to do with the z-index of the DisplayObject. What that means is even though the DisplayObject appears to be further away and smaller, it will still be in front of closer DisplayObjects unless you update it's position in the display list.
Flex 4 solves this by adding a layer property to UIComponent. For the List component for example, this allows you to specify a different display list index for the item renderer compared to where it is located in the data provider. You simply set the layer property for each element (based on its z property ideally) and if required call container.invalidateLayering()
OpenFlux handles this automatically after the layout is done setting the position of each child.
Animation?
One question I'm hoping someone has a decent answer to is regarding animating the size/position of child elements. For example, if I switch layouts I want the children to be tweened to their new positions. This is easy to do with OpenFlux but I have no idea how to do it with Flex 4. I know Flex 3 introduced a dataChangeEffect but this seems to have disappeared with the Flex 4 List component.
What next?
So, I only implemented the very basics of the layout. Next steps would be to add support for measure, scrolling and virtualization. I've included a LayoutBase3D class which handles common 3D tasks. I'd love to see what layouts others come up with and think it would be cool to start a Flex 4 Layouts open source project.
Feel free to write any questions in the comments.
OpenFlux Independant From Flex
Over the last month I've been working on getting OpenFlux independant from UIComponent and many of the other large Flex classes with a goal to create a much ligher framework.
OpenFlux Application (77KB)
Flex Application with OpenFlux Components (205KB)
I have two applications above that look exactly the same. The difference is one is a OpenFlux application with OpenFlux components and the other is a Flex application with OpenFlux components. Although the code is almost identical, the OpenFlux app compiles to 77kb and the Flex app compiles to 205kb. Before you think "oh great another framework" I'd like to point out the following:
1. OpenFlux components can be used with or without Flex
OpenFlux components all extend a class (currently called PhoenixComponent) that implements IUIComponent allowing them to work with or without Flex. Likewise, you can use Flex classes and projects like Degrafa and Mate with pure OpenFlux applications.
2. This is not a completely separate framework, just lighter weight implementations of Flex's interfaces
We'll continue to use the parts of Flex that work well but replace the parts can be done better. Luckily the Flex team uses interfaces well allowing us to use our own implementations for almost every piece of the framework.
3. MXML, CSS, Resource Bundles and Data Binding all still work with pure OpenFlux apps
These 4 features of Flex make our lives as developers way easier and I wouldn't have even bothered continuing getting OpenFlux independant from Flex if it ment I'd have to build all my applications in pure AS3. Utilizing these features do add size to your compiled application but I think the benefits they provide make it well worth it.
4. Flex is monolitic, OpenFlux is modular.
My opinion is if your application is loaded over the internet it should be highest priority to keep the application size small and don't include any code that you aren't utilizing. For example, the List component in this application doesn't need drag n' drop support so that code isn't included.
Even if create a basic Flex application with just a List component that application's optimized compile size is 250kb. Actually, an OpenFlux application is even smaller then a Flex application that uses Runtime Shared Libraries. I think 77kb even is too large though and it's an on going effort to continue reducing the size of OpenFlux applications.
So what's next?
Our goal is to have an OpenFlux SDK you can use with Flex Builder and an OpenFlux.org website available in time for 360|Flex Indianapolous. I have a session called "OpenFlux and Flex 4" where I will discuss the differences between the two frameworks, give examples on when to use one over the other and how you can use them both together.
Over the last month of coding/experimenting we weren't even sure if our goals were possible. Now that we've been able to accomplish mainly what we hoped for we'll be focusing on resolving issues, documentation and examples.

