Archive

Archive for the ‘flex’ Category

Flex Large Book Component

September 10th, 2008 3 comments

I needed a book control for an AIR app and the best that suited my needs was Ruben Swieringa’s Flex Book component (many thanks for building this). I had to use this for a 200+ page magazine and I quickly discovered that it worked a little slow for this amount of pages. After a profiling session I realized that what took so long was the Flash pre-render time because all the pages are in the display list (one on top of another). So I wrote a some code to use only 8 pages (4 pairs): the rest are stored in an array. I also added a jumpToPage method to make navigation easier in a 200+ page book.

Still to be done:

  • if you have more than one transparent page one after another it will look very messy because at any given moment the book has only 8 pages. This can be done by configuring how many real pages are stored … but the logic of navigating through get’s very nasty.
  • tearing pages doesn’t work (not implemented yet)
  • lot of traces are still enabled
  • BEWARE of bugs :)

Give it a try:

image

Categories: flex Tags:

Using Import Web Service wizard to connect Flex to .NET

July 28th, 2008 13 comments

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>
Categories: flash builder, flex Tags:

DataGrid – Confirm a Grid change event using an Alert popup

July 9th, 2008 No comments

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 :D ataGridEvent):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>
Categories: flex, tips & tricks Tags:

Identifying visual elements in Flex

June 16th, 2008 No comments

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)">
Categories: debugging, flex Tags: