Wednesday, January 28, 2009

Accessing proxied object

When receiving objects back from a server, they are usually wrapped up as a ObjectProxy. I wanted to know how I could access the protected object property on the ObjectProxy, so here's how you do it:
import mx.utils.ObjectProxy;
import mx.utils.object_proxy;
import mx.rpc.events.ResultEvent;

private function resultHandler(event:ResultEvent):void {
    var proxy:ObjecyProxy = ObjectProxy(event.result);
    var obj:Object = proxy.object_proxy::object;
}

I found the solution from this useful website:
http://www.docsultant.com/site2/articles/flex_internals.html

Monday, January 19, 2009

FormItem label verticalAlign

As far as I've seen the label on FormItem's are always vertically aligned at the top. I have no idea why the Adobe guys didn't add the expected "verticalAlign" style to let the programmer choose where the label is positioned.

Anyways, I've extended the default mx.containers.FormItem control to add support for this style:
public class FormItemVerticalAlign extends FormItem 
{   
    override protected function updateDisplayList(w:Number, h:Number):void {
        super.updateDisplayList(w, h);   
        // vertically align (top by default)
        var verticalAlign:String = getStyle("verticalAlign");
        if (verticalAlign == "middle") {   
            itemLabel.y = Math.max(0(h - itemLabel.height2);
        else if (verticalAlign == "bottom") {
            var padBottom:Number = getStyle("paddingBottom");
            itemLabel.y = Math.max(0, h - itemLabel.height - padBottom);
        }
    }  
}

E.g.

Wednesday, January 7, 2009

HTTPService performance of the various result formats

Today I was reading about the various result formats options available for using with HTTPService requests. These formats are:
  • object (default) - the resulting xml is returned as an ObjectProxy, or an ArrayCollection of ObjectProxy objects
  • array - the root object is returned as the first item in an Array
  • xml - returns the well formed xml (as an XMLNode object)
  • e4x - returns the response as an XML object
  • flashvars - result is formatted into name=value pairs like "name=value&on=true"
  • text - returns the response as a String object
Have you ever wondered which one is the fastest?

I ran some tests on an XML file that had 22,000 lines, and here are the results:
  • object: 610ms
  • array: 600ms
  • xml: 244ms
  • flashvars: 121ms
  • text: 51ms
  • e4x: 113ms
And here is the code I used to calculate the times:
private var startTime:int;

private function loadXMLFile(format:String):void {
    var service:HTTPService = new HTTPService();
    service.url = "huge.xml";  // located in the project src directory
    service.resultFormat = format;
    service.headers["Pragma""no-cache";  // no caching of the file
    service.headers["Cache-Control""no-cache";
    service.addEventListener(ResultEvent.RESULT, resultHandler);
    startTime = getTimer();
    var token:AsyncToken = service.send();
    token.resultFormat = format;
}
   
private function resultHandler(event:ResultEvent):void {
    var time:int = getTimer() - startTime;
    trace(event.token.resultFormat + ": " + time + "ms");
}

Notes: there are static constants for the 6 result formats in HTTPService.
I haven't done any calculations on how long it would take to parse the XML vs. working with the ObjectProxy objects. And obviously if you are working with other files types besides XML then the results will be different.

Out of curiosity I also tested how long it would take to load the same file using a different method using the URLLoader and URLRequest classes. The result was usually around 80ms, but that was just to return the contents of the file. When converted into an XML object it was closer to 120ms.

Friday, December 12, 2008

Resizable Movable Panel

Following on the examples I found at this blog http://blogs.adobe.com/flexdoc/2007/03/creating_resizable_and_draggab.html

** I've posted an updated version here that has more advanced resize/move support.

I created my own resizable window component which extends TitleWindow. It renders a small resize handle in the bottom right corner of the panel which the user can drag to resize the window. To make the window resizable, set the resizable property to true.

The window can also be dragged by the titlebar to move it (assuming that it is the child of a container that uses an absolute layout). To make the window movable, set the movable property to true. Then you'll see a drag handle in the titlebar.

The example below uses the PopUpManager to show the window as a popup (which lets the user move the panel around the screen). You can view the source from the context menu. This window also listens for Enter and Escape keyboard events which both hide the popup. The window is hardcoded to have a min width and height of 20, and a max width/height of the application's width/height.

Thursday, December 11, 2008

Dynamically changing the browser title in ActionScript

Many of you have probably set the Application.pageTitle property. But as the documentation says, that property can only be set in MXML. So how do you change it dynamically in ActionScript?

One way that I found is to use the ExternalInterface class and use JavaScript like this:
ExternalInterface.call("eval(window.document.title = 'New Title')");

Obviously you'd want to escape any single quotes in the new title.

One other way I found to do this is using the BrowserManager(if you have it enabled):
var browser:IBrowserManager = BrowserManager.getInstance();
browser.init("""New Title");
// or this way:
browser.setTitle("New Title");

Hope this helps!