This is one cool conference for Flash content creators, be they designers, developers, artists, animators or anybody interested in Flash. But what’s even cooler is that we (the European platform evangelist team) have some tickets to give away. To have a chance to win one of the 6 tickets you need to send us a nice picture with you, Flash, Flex and AIR and a beach. If you won’t have a chance to get to the beach by then, don’t worry! You can just get the beach in the picture by using some digital help … like Photoshop for example :).

Please submit the pictures on Serge’s blog. He will collect them until September 8 and then each of us will pick his favorite. The creator will win the conference pass (a £499/€633 value).

Are you using HTML/JS to build AIR Applications and wondering how to automate functional testing for your app? Here is some news that might put a smile on your face. In few words, the guys across my desk have been tweaking Selenium to work on AIR. Mihai wrote a cool blog post about how you can test drive this bit of code so if you are interested please take it for a spin. Don’t forget to tell us how it was!

If you followed my previous post you probably now have a Flex + .NET project that makes a WebService call. If not, here’s a project you can use testDotNet.zip. To import this in Flex Builder choose File->Import->Flex Project and follow the steps.

Next open Visual Web Developer and open a Web Site in the same location as the Flex Builder project.  Open web.config and make sure you have <compilation debug=”true”> (this inserts debugging symbols for the .NET code).

Now we need to use the same ASP.NET Developer Server for both the Flex Builder and Visual Web Developer. Since by default both tools try to start one instance we need a little trick to do that:

Start the MXML project through Flex Builder; this will start ASP.NET Developer Server usually on port 3000. Then go to Visual Web Developer; on Project Property Page (Right Click on the Project in the Solution Explorer) click Start Options and select Use Custom Server and enter http://localhost:3000/testDotNet/

image

Start also the .NET project just to connect the Visual Web Developer to the ASP.NET Developer Server instance. Now you will be able to debug both Flex and .NET code:

image

image

Since I was deeply involved in Flex Builder support for working with .NET I thought that it would be a good idea to write some articles on how you can use these technologies together. I will create a “Hello World” project but the focus will be on how you can better make use of the available tools.

For tooling I will be using Flex Builder and Visual Web Developer 2008 Express Edition (VWD).

First let’s create a simple ASP.NET Web Service project using VWD:

image

 

I slightly modified the HelloWorld method in Service.cs to receive a parameter:

[WebMethod]
public string HelloWorld(String name) {
    return “Hello “ + name + “! Nice talking to you!”;
}

 

Now let’s get into Flex Builder and try to get something from the .NET Server. First we will create a new Flex Project on top of the .NET one. To do that click on New->Flex Project and choose ASP.NET as the server technology:

image

Make sure the location is the same as the VWD .NET project. Now run the default MXML file to start the ASP.NET Developer Server.

Next we will generate the glue code for calling the Web Service using the Import Web Service Wizard. Choose Data -> Import Web Service (WSDL) from the Flex Builder menu. On the first page the main source folder is selected by default. You can leave it like this. On the second page you need to choose the WSDL URI. When you launched the MXML application the ASP.NET Developer Server should have started by default on port 3000 (see the tray icon). In this case the WSDL URL should be something like http://localhost:3000/testDotNet/Service.asmx?WSDL.

image

The third page should look like this:

image

Now you should have some typed AS classes that provide easy access the .NET Web Service methods. The cool thing about this is that Flex Builder knows now how to do autocompletion on Web Service calls. So making a little application that will showcase this is just too easy:

<?xml version=”1.0″ encoding=”utf-8″?>
<mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml” layout=”absolute”>
    <mx:Script>
        <![CDATA[
            import mx.controls.Alert;
            import generated.webservices.HelloWorldResultEvent;
            import generated.webservices.Service;
            public function sayHello():void {
                var service:Service = new Service();
                service.addhelloWorldEventListener(
                    function (event:HelloWorldResultEvent):void {
                        Alert.show(event.result);
                    });
                service.helloWorld(myName.text);
            }
        ]]>
    </mx:Script>
    <mx:TextInput x=”176″ y=”171″ id=”myName”/>
    <mx:Text x=”70″ y=”173″ text=”Enter Your Name”/>
    <mx:Button x=”344″ y=”171″ label=”Click to receive greeting” click=”sayHello()”/>
    
</mx:Application>

I was playing with sound in flash having, among other things, to do a little fade effect. So my first impulse was to use an effect to animate the volume property. Too bad that the SoundChannel object is a Flash one … and to use Flex effects you need to have bindable objects and properties. To do that you can wrap the flash object inside one that is bindable (or has bindable properties), using some some kind of Proxy Pattern.

Here’s a little sample for the volume of the SoundChannel:

package com.pricope.miti.sound

{

    import flash.media.SoundChannel;

    import flash.media.SoundTransform;

    public class SoundChannelProxy

    {

        public var channel:SoundChannel;

        public function SoundChannelProxy()

        {

        }

        [Bindable]

        public function set volume(vol:Number):void {

            var tmSnd:SoundTransform = channel.soundTransform;

            tmSnd.volume = vol;

            channel.soundTransform = tmSnd;

        }

        public function get volume():Number {

            return channel.soundTransform.volume;

        }

    }

}

and here is a little app that illustrates this (View Source Here):

Today I saw an interesting post on FlexCoders. Suppose you have an editable DataGrid and you want to confirm through an Alert if the change should be made or not. Preventing the change is easy, you just need hook onto the itemEditEnd and call event.preventDefault(). The problem arises when you want to confirm this with the user using an Alert. This is because the Alert.show call is asynchronous. This means that the grid event will complete before the user can choose Yes or No.

public function editEnd(event:DataGridEvent):void {
    
  Alert.show("Do you want to save changes?","Save changes",Alert.YES | Alert.NO,null,function(ev:CloseEvent):void {
      if (ev.detail == Alert.YES) {
        //LABEL2: This will be reached long after the LABEL1 has been reached. 
        //So at this point the grid has been executed the default behavior for the change event
      }
    });
    //LABEL1: Because of the asynchronous nature this will be reached right after the Alert.show call    
 
}

So my idea of solving this was to save the new value, prevent the default grid behavior of updating the dataProvider and update the data provider manually on the Alert.show closeHandler.

Here is some code that illustrates this:

<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml"
        initialize="initData()" layout="absolute">
  <mx:Script>
   <![CDATA[
       import mx.controls.TextInput;
       import mx.controls.Alert;
    import mx.collections.*;
    import mx.events.*;
    
      private var DGArray:Array = [
         {Artist:'Pavement', Album:'Slanted and Enchanted', Price:11.99},
         {Artist:'Pavement', Album:'Brighten the Corners', Price:11.99}];
         
      [Bindable]
      public var initDG:ArrayCollection;
      public function initData():void {
         initDG=new ArrayCollection(DGArray);
      }
      
      public function editEnd(event:DataGridEvent):void {
          
          //Save the data before calling Alert
        var myEditor:TextInput = 
                    TextInput(event.currentTarget.itemEditorInstance);
                
        // Get the new value from the editor.
        var newVal:String = myEditor.text;    
        var dataObject:Object = event.itemRenderer.data;
        var property:String = event.dataField;
          
        Alert.show("Do you want to save changes?","Save changes",Alert.YES | Alert.NO,null,function(ev:CloseEvent):void {
            //If we have clicked YES then update the data collection manually
            if (ev.detail == Alert.YES) {
                  dataObject[property] = newVal.toString();
                  initDG.itemUpdated(dataObject,property);
            }
          });
          
          //prevent data grid to update his dataProvider collection
          event.preventDefault();
      }
   ]]>
   </mx:Script>
 
   <mx:DataGrid id="myGrid" width="350" height="200" 
      dataProvider="{initDG}" editable="true" itemEditEnd="editEnd(event)" >
      <mx:columns>
         <mx:DataGridColumn dataField="Album" />
         <mx:DataGridColumn dataField="Price" />
      </mx:columns> 
   </mx:DataGrid>
   <mx:DataGrid id="readOnlyGrid" width="350" height="200" 
      dataProvider="{initDG}" x="0" y="208">
      <mx:columns>
         <mx:DataGridColumn dataField="Album" />
         <mx:DataGridColumn dataField="Price" />
      </mx:columns> 
   </mx:DataGrid>
</mx:WindowedApplication>

A few days ago I was trying to use the FDS AJAX Bridge to push some messages in an AJAX grid. So I created a Flex + WTP + BlazeDS project and went to change the default Application from the default MXML file to my FDMSBridge.as (The 1×1 pixel SWF). Guess what? You can’t add AS files, only MXML ones

image

This might be a little bug, but I found a workaround. I manually edited .actionScriptProperties file and in the <application> section added the FDMSBridge.as:

<?xml version="1.0" encoding="UTF-8"?>
<actionScriptProperties mainApplicationPath="testBlaze.mxml" version="3">
<compiler additionalCompilerArguments="-services &quot;C:/work/wksp/samples/testBlaze/WebContent/WEB-INF/flex/services-config.xml&quot; -locale en_US" copyDependentFiles="true" enableModuleDebug="true" generateAccessible="false" htmlExpressInstall="true" htmlGenerate="true" htmlHistoryManagement="true" htmlPlayerVersion="9.0.28" htmlPlayerVersionCheck="true" outputFolderPath="bin-debug" rootURL="http://localhost:8080/testBlaze" sourceFolderPath="flex_src" strict="true" useApolloConfig="false" verifyDigests="true" warn="true">
<compilerSourcePath/>
<libraryPath defaultLinkType="1">
<libraryPathEntry kind="4" path=""/>
<libraryPathEntry kind="1" linkType="1" path="flex_libs"/>
</libraryPath>
<sourceAttachmentPath/>
</compiler>
<applications>
<application path="FDMSBridge.as"/>
<application path="testBlaze.mxml"/>
</applications>
<modules/>
<buildCSSFiles/>
</actionScriptProperties>

Now the FDMSBridge.as should be compiled as a normal Flex application:

image

I recently started working on a project to internationalize a large Flex App. One of the problems of internationalizing UIs is that in different languages the same text might grow not only horizontally but also vertically (e.g.: In Chinese the default height is often 16 pixels and not 10 or 12 as in most European languages). So if you have an application that didn’t take that into account (my case) you need to rethink the layout to accommodate this expansion. But my very first problem when I started to look into that application was that I had no clue where where each visual element is defined and:

  • the application is BIG
  • The guys that wrote it are on a time zone 10 hours away

So I was basically on my own to identify visual elements, figure out what the actual layout is and where it is defined.

So I came up with this trick to get a sense on how this application is built:

In the capture phase, the visual events in AS3 are dispatched from the root ancestor to the target. This means that the Application container receive all events. So I registered a listener on the Application container that analyzes these events, finds the actual target and then displays the entire display stack that contains the target object. This helped me identify what AS class represents which visual element and in what container this element is placed.

Here’s is my little bit of code that does this:

public function initTrace(app:WindowedApplication):void {

    app.addEventListener(MouseEvent.MIDDLE_CLICK,middleClickHandler,true);

}

public function middleClickHandler(event:MouseEvent) {

    var tm:Object = event.target;

    var tab:String = "";

    traceObj(tab,tm);

    var tmParent:DisplayObject = tm as DisplayObject;

    while (tmParent != null) {

        tab += "  ";

        traceObj(tab,tmParent);

        tmParent = tmParent.parent;

    }

}

public function traceObj(tab:String,obj:Object):void {

    trace(tab + getQualifiedClassName(obj));

    if (obj is UIComponent) {

        var tmUI:UIComponent = obj as UIComponent;

        trace(tab+tmUI.getStyle("fontFamily") + ":" + tmUI.getStyle("fontSize"));

    }

}

You just need to call the initTrace method on Application.applicationComplete:

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"

    layout="absolute" applicationComplete="initTrace(this)">

So I am a big fan of debugging. I know that for most people this isn’t exactly what they get out of the bed in the morning, but nevertheless I know that this prevents them going to sleep in the evening. My first thing when I look into a technology and it’s tools ecosystem is “how will I debug this?”. I find more useful to spend some time configuring my environment for debug earlier in the project rather than later, when things might get hotter.

These days I was looking into Flex and PHP and naturally I started by trying to configure my environment so I can debug this. My goal was to be able to to debug both Flex code and PHP code, to track the dataflow through a server request. I’ve tried different solutions, and here is the simpler one:

Solution

First installed Zend Studio for Eclipse (http://www.zend.com/en/products/studio/downloads). Make sure you install also the Zend Studio Toolbar for your browser.

Next installed the Flex Builder Plugin from (http://www.adobe.com/cfusion/tdrc/index.cfm?product=flex_eclipse) and choose as Eclipse location the folder where you installed Zend Studio (Usually c:\Program Files\Zend\Zend Studio for Eclipse - 6.0.0\ for my Windows machine). You might get the following warning:

image

You just need to follow the 3 steps and it should be fine.

The next thing is to install the Zend Debugger server. I found a good tutorial here so I will not get into much detail.

Now we will create a combined Flex + PHP Project:

  • New -> Flex Project
  • Choose PHP as Application Server Type

image

image

I will use the following MXML File:

<?xml version=”1.0″ encoding=”utf-8″?>
<mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml” layout=”absolute” applicationComplete=”initApp()”>
    <mx:Script>
        <![CDATA[
            import mx.rpc.events.ResultEvent;
            import mx.rpc.http.HTTPService;
            var gateway:HTTPService = new HTTPService();

            function initApp() {
                gateway.url = "hello.php";
                gateway.method = "POST";
                gateway.useProxy = false;
                gateway.addEventListener(ResultEvent.RESULT, resultHandler);

            }
            function sendRequest():void {
                gateway.request =  {"name":enteredName.text};
                gateway.send();

            }

            function resultHandler(e:ResultEvent):void {
                myText.text = e.result.toString();
            }
        ]]>
    </mx:Script>
    <mx:Button x=”301.5″ y=”10″ label=”Send” click=”sendRequest()”/>
    <mx:Text id=”myText” x=”10″ y=”62″ width=”493″ height=”181″ fontFamily=”Arial” fontSize=”36″/>
    <mx:Label x=”10″ y=”12″ text=”Enter Your Name:”/>
    <mx:TextInput id=”enteredName” x=”121″ y=”10″/>
</mx:Application>