flex spaghetti

Just another WordPress.com weblog

Paging Data in Spark Components (AsyncListView)

Posted by rvollmar on November 20, 2009

There’s a new class, mx.collections.AsyncListView, which implements IList and takes an IList. It sits between the Spark component and the data source. So to use it:
– Set a List’s dataProvider property equal to an AsyncListView.
– Set the AsyncListView’s list property equal to the data source, such as DataService.

Now, AsyncListView will handle all the ItemPendingErrors coming from the data source and give the List either objects from the data source, pending objects, or failed objects. The developer defines functions for the AsyncListView to call when items fail or are pending; the objects returned from these functions are put into the List. To set up these functions, set the createPendingItemFunction and createFailedItemFunction properties.

The main outstanding issue, which we aren’t going to fix now, is that sorting/dragging/dropping of pending and failed items isn’t supported. See SDK-23911 for details.

Here’s an example which pages data from a DataService to a List. The pending function returns “item x pending”, and the fail function returns “item x failed”. The item renderer in the list draws a white background for successful items, a green background for pending items, and a red background for failed items.

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:s="library://ns.adobe.com/flex/spark" 
    xmlns:mx="library://ns.adobe.com/flex/halo" minWidth="1024"
    minHeight="768">
  <fx:Script>
    <![CDATA[
      public function pendingFunction(i:int, obj:Object):Object{
        return {value: "item " + i.toString() + " pending"};
      }
      public function errorFunction(i:int, obj:Object):Object{
        return {value: "item " + i.toString() + " failed"};
      }
      
      public function doFault(e:* = null):void{
        //trace("DataService fault");
      }
    ]]>
  </fx:Script>
  
  <fx:Declarations>
    <s:DataService id="ds" destination="pagingTest" fault="doFault()" />
  </fx:Declarations>
  <s:Button x="100" y="0" label="Get Data" click="ds.fill(lcv)"/>
  <s:List x="100" y="50" id="theList" useVirtualLayout="true" 
    height="300" width="300" fontSize="18">    
    <s:dataProvider>
      <mx:AsyncListView id="theView"
              createPendingItemFunction="pendingFunction"
              createFailedItemFunction="errorFunction">
        <mx:list>
          <mx:ListCollectionView id="lcv" />
        </mx:list>
      </mx:AsyncListView>
    </s:dataProvider>
    
    <s:itemRenderer>
      <fx:Component>
        <s:ItemRenderer width="100%" height="100%">
          <fx:Script>
            <![CDATA[
              import mx.graphics.SolidColor;
              
              private function getColor(obj:Object):uint{
                if(obj == null)
                  return 0xffffff;
                else if(obj.value.indexOf("pending") > -1)
                  return 0x00ff00;
                else if(obj.value.indexOf("failed") > -1)
                  return 0xff0000;
                else
                  return 0xffffff;
              }
              
              override public function set data(obj:Object):void{
                super.data = obj;
                try{                
                  nameLabel.text = (obj.value) as String;
                  nameLabel.setStyle('backgroundColor', getColor(obj));
                }catch(e:Error){
                  //trace("Error for " + obj + ", " + e.message);
                }
              }
            ]]>
          </fx:Script>
          <s:states>
            <s:State name="normal" />
            <s:State name="hovered" />
            <s:State name="selected" />
          </s:states>
          <s:Label id="nameLabel" width="100%" height="100%" paddingTop="5"
            paddingBottom="5" paddingLeft="5" paddingRight="5" />
          <s:Rect width="100%" height="100%" id="theRect" />
        </s:ItemRenderer>
      </fx:Component>
    </s:itemRenderer>
  </s:List>
</s:Application>

Posted in AsyncListView, List, Paging | 1 Comment »

One label function serving multiple DataGridColumns

Posted by rvollmar on November 19, 2009

If you want to format several columns of your DataGrid the same way, it may initially look like you need to create several identical label functions, one per column. However, you can get away with defining just one. e.g.


<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
    
    <mx:Script>
        <![CDATA[
            import mx.formatters.CurrencyFormatter;
            
            private function theLabelFunction(item:Object, 
                            column:DataGridColumn):String{
                var val:Number;
                var formatter:CurrencyFormatter = new CurrencyFormatter();
                
                formatter.precision = 0;
                formatter.rounding = "nearest";
                val = item[column.dataField];
                
                return formatter.format(val);
            }
        ]]>
    </mx:Script>
    
    <mx:DataGrid id="dg1" >
        <mx:dataProvider>
            <mx:ArrayCollection>
                <mx:Object checking="100.22" savings="2000" under_pillow="0" />
                <mx:Object checking="0" savings="0" under_pillow="5000" />
                <mx:Object checking="1000" savings="23.88" under_pillow=".5" />
            </mx:ArrayCollection>            
        </mx:dataProvider>
        
        <mx:columns>
            <mx:DataGridColumn dataField="checking" 
                               headerText="Checking" 
                               labelFunction="theLabelFunction" />
            <mx:DataGridColumn dataField="savings" 
                               headerText="Savings" 
                               labelFunction="theLabelFunction" />
            <mx:DataGridColumn dataField="under_pillow" 
                               headerText="Under Pillow" 
                               labelFunction="theLabelFunction" />
        </mx:columns>
    </mx:DataGrid>
    
</mx:Application>

Posted in DataGrid | Leave a Comment »

TileLayout Example

Posted by rvollmar on November 17, 2009

Here’s a quick example of using a TileLayout for a List and positioning elements within it:

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
  xmlns:s="library://ns.adobe.com/flex/spark" 
  xmlns:mx="library://ns.adobe.com/flex/halo">
  <s:VGroup>
    
    <s:HGroup>
      <s:Button label="horizontalAlign left" click="TileLayout(list1.layout).horizontalAlign = 'left'" />
      <s:Button label="horizontalAlign center" click="TileLayout(list1.layout).horizontalAlign = 'center'" />
      <s:Button label="horizontalAlign right" click="TileLayout(list1.layout).horizontalAlign = 'right'" />
    </s:HGroup>  
    <s:HGroup>
      <s:Button label="verticalAlign top" click="TileLayout(list1.layout).verticalAlign = 'top'" />
      <s:Button label="verticalAlign middle" click="TileLayout(list1.layout).verticalAlign = 'middle'" />
      <s:Button label="verticalAlign bottom" click="TileLayout(list1.layout).verticalAlign = 'bottom'" />
    </s:HGroup>    
    <s:List id="list1"  >
      <s:itemRenderer>
        <fx:Component>
          <s:ItemRenderer width="10" height="10">
            <s:Rect width="100%" height="100%" >
              <s:stroke>
                <mx:SolidColorStroke weight="1" color="{data.color}"/>
              </s:stroke>
            </s:Rect>
          </s:ItemRenderer>
        </fx:Component>
      </s:itemRenderer>
      <s:layout>
        <s:TileLayout horizontalAlign="center" 
                verticalAlign="middle"
                columnWidth="40" rowHeight="40" />
      </s:layout>
      <s:dataProvider>
        <mx:ArrayCollection>
          <fx:Object color="0xff0000" />
          <fx:Object color="0x00ff00" />
          <fx:Object color="0x0000ff" />
          <fx:Object color="0xffff00" />
        </mx:ArrayCollection>
      </s:dataProvider>
  </s:List> 
  </s:VGroup>
</s:Application>

Posted in Group, Layout, List | Leave a Comment »

Application.application returns null.

Posted by rvollmar on June 21, 2009

Just a quick note:
If you have started using s:Application, you’ll find that mx.core.Application.application returns null. We’ve deprecated that syntax; the replacement is mx.core.FlexGlobals.topLevelApplication. To read about more backwards compatibility issues, here’s a helpful article: http://labs.adobe.com/wiki/index.php/Flex_4:Backward_Compatibility
All the best!
– Rob

Posted in Application | Leave a Comment »

Creating states in a skin

Posted by rvollmar on June 21, 2009

You may want to change the attributes of a component’s skin depending on the state the component is in. In this case, we’re going to make a skin for the Application class which changes its background depending on the state it’s in:

happy: yellow background
sad: blue background
sophisticated: various shades of grey
bland: white background

1. Copy frameworks/projects/flex4/src/spark/skins/spark/ApplicationSkin.mxml to the directory you’re working in and rename it. I’m calling it SkinWithStates.mxml.

2a. Find the states section and add some states.
2b. Find the backgroundRect and make its fill stateful. Also, add a couple more Rects for the sophisticated state. Note that the subsequent Rects have left/right/top/bottom set to increasing numbers, so they will appear nested. Here is how the skin file should look when it’s done:

<?xml version="1.0" encoding="utf-8"?>

<!--- The default skin class for the Spark Application component. 
        
      @langversion 3.0
      @playerversion Flash 10
      @playerversion AIR 1.5
      @productversion Flex 4
-->
<s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009"
    xmlns:s="library://ns.adobe.com/flex/spark"
    alpha.disabled="0.5" >

    <fx:Metadata>
    <![CDATA[ 
        [HostComponent("spark.components.Application")]
    ]]>
    </fx:Metadata> 
    
    <s:states>
     <s:State name="normal" />
     <s:State name="disabled" />
        <s:State name="sad" />
        <s:State name="happy" />
        <s:State name="sophisticated" />
        <s:State name="bland" />
    </s:states>
    
    <s:Rect id="backgroundRect" 
        left="0" right="0" 
        top="0" bottom="0">
        <s:fill>
            <s:SolidColor color.sad="0x0000ff"
                          color.happy="0xffff00"
                          color.sophisticated="0x000000"
                          color.bland="0xffffff" />
        </s:fill>
    </s:Rect>
    
    <s:Rect id="backgroundRect2"
        left="20" right="20"
        top="20" bottom="20">
        <s:fill>
            <s:SolidColor color.sad="0x0000ff"
                          color.happy="0xffff00"
                          color.sophisticated="0x444444"
                          color.bland="0xffffff" />
        </s:fill>
    </s:Rect>

    <s:Rect id="backgroundRect3"
        left="40" right="40"
        top="40" bottom="40">
        <s:fill>
            <s:SolidColor color.sad="0x0000ff"
                          color.happy="0xffff00"
                          color.sophisticated="0x888888"
                          color.bland="0xffffff" />
        </s:fill>
    </s:Rect>
        
    <s:Group id="contentGroup" left="0" right="0"
    top="0" bottom="0"
    minWidth="0" minHeight="0"/>

</s:Skin>

3. Override the getCurrentSkinState() method in a subclass of Application. This method should do whatever analysis is needed to figure out what state the skin should be in, and return a string containing that state’s name. Here is an example which just returns the mood, which is the name of a state. Save it as TestApplication.as:

package{

    import spark.components.Application;

    public class TestApplication extends Application{
    
        public var mood:String;

        // Constructor.
        public function TestApplication():void{
            mood = "bland";
        }
    
        // Return the state the skin should be in.
        override protected function getCurrentSkinState():String{
            return mood;
        }   
    }
}

4. Make a main application file which uses the subclass and the skin just created:

<?xml version="1.0" encoding="utf-8"?>
<custom:TestApplication 
    xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:mx="library://ns.adobe.com/flex/halo" 
    xmlns:s="library://ns.adobe.com/flex/spark"
    xmlns:custom="*"
    skinClass="SkinWithStates" >

<fx:Script>
<![CDATA[

    private function doMoodChange(e:Event):void{
        this.mood = e.currentTarget.selectedValue;
        
        // This causes the skin's state to
        // be evaluated again.
        invalidateSkinState();
    }

]]>
</fx:Script>

<fx:Declarations>
    <s:RadioButtonGroup id="group1" 
        itemClick="doMoodChange(event)" />
</fx:Declarations>

<s:Group x="50" y="50">
    <s:layout>
        <s:VerticalLayout />
    </s:layout>

    <s:SimpleText text="Choose Mood:" />
    
    <s:RadioButton id="rbHappy" 
                   groupName="group1" 
                   label="happy" value="happy" /> 
    <s:RadioButton id="rbSad" 
                   groupName="group1" 
                   label="sad" value="sad" /> 
    <s:RadioButton id="rbSophisticated" 
                   groupName="group1" 
                   label="sophisticated" 
                   value="sophisticated" /> 
    <s:RadioButton id="rbBland" 
                   groupName="group1" 
                   label="bland" 
                   value="bland" 
                   selected="true" /> 
</s:Group>

</custom:TestApplication>

Posted in Application, Skins, States | Leave a Comment »

Fetching and building Flex source code with a Mac

Posted by rvollmar on June 13, 2009

For the Mac users out there, here are some instructions for fetching the latest Flex SDK source code (aka “trunk”). Note that I’m saying LATEST. It might not be stable. Heck, it might not even build.

For a GUI client, I use SmartSVN because it was the first one I stumbled over which:
– Has a free, functional version.
– I figured out how to use quickly.

If you can recommend another, please point me to it. I’ll be happy to give it a try and post instructions.

Of course, the instructions are basically the same on any OS. But it’s always nice to see very specific instructions for the OS one is using.

Instructions using the svn command line client:
1. Get it (http://downloads.open.collab.net/binaries.html) and install it.
2. Run this command:

svn checkout http://opensource.adobe.com/svn/opensource/flex/sdk/trunk local-directory

Instructions using SmartSVN (6.0.2):
1. Get it (http://www.syntevo.com/smartsvn/index.html), install it, and start it.
2. Project > Check Out.
3. Choose Quick Checkout and fill in:
URL: http://opensource.adobe.com/svn/opensource/flex/sdk/trunk
Local Directory: whatever works for you
4. Click Continue, then Finish.

Building the SDK:
Assuming you have recent releases of Ant (I have 1.7.0) and Java (I have 1.5.0_16-133):
1. Bring up a terminal window.
2. cd to the trunk directory that you fetched above.
3. Run: ant clean main

Note: I don’t have FLEX_HOME, JAVA_HOME, or ANT_HOME defined anywhere, but there is some documentation which claims these are needed. Do what works for you.

References:
Getting source code: http://opensource.adobe.com/wiki/display/flexsdk/Get+Source+Code
Building the SDK: http://opensource.adobe.com/wiki/display/flexsdk/Build+and+Test

Posted in Source | Leave a Comment »

Setting the layout property in Flex 4

Posted by rvollmar on June 13, 2009

In Flex 3, the layout property could be set to strings such as “absolute”, “horizontal”, and “vertical”. In Flex 4, the layouts are classes such as BasicLayout, HorizontalLayout, VerticalLayout, and TileLayout. If you try to set the layout property in a class’ MXML tag, you will get the compiler error “values of type spark.layouts.supportClasses.LayoutBase cannot be represented in text.” Here are some options:

1. To set the layout for the Application in MXML:

<s:Application ...>
    <s:layout>
        <s:VerticalLayout />
    </s:layout>
...

2. To set the layout for a Group:

<s:Group>
    <s:layout>
        <s:VerticalLayout />
    </s:layout>
...

3. That seemed verbose, so there’s a shortcut to set the layout for a Group; you can use VGroup and HGroup:

<s:VGroup>
...

Enjoy,
– Rob

Posted in Application, Group, Layout | Leave a Comment »

A class is missing!

Posted by rvollmar on June 13, 2009

You may notice that code completion seems to fail for some classes. If this is happening to you, try pressing control + space twice. In order to guide developers into using the new Spark classes, code completion has been turned off by default for certain Halo (mx) classes.

To modify this behavior, select Window > Preferences > Flash Builder > Editors > MXML Code > Advanced. This control shows the order of the suggestions as you repeatedly press control + space. Moving “All” to the top will allow all classes matching your partial word to be suggested in the initial code completion hint.

– Rob

Posted in Builder | Leave a Comment »

“We file bugs and they go into a black hole”

Posted by rvollmar on February 17, 2009

I saw a comment like this recently and thought it would be a good thing to address. I’ve thought about it, and there are a few areas where bugs seem to…linger. The good news is that usually you can do something about it.

Community

Community members need to take action on bugs with a Community status. Specifically, vote on them!! Two votes will move a bug to the New status; that’s when they show up in QE bug queues. Sometimes we like to look through Community bugs on our own just because, but please don’t rely on it!

Info Needed

When we need information from someone, we add a comment and set the status to Info Needed. You, the diligent user, promptly provide the information, and then the bug just sits there. Sound familiar? This is because we expect users to click on the “Info Supplied” link on the left. That will kick the bug back into our queues. How would you know to do this? Well, until now you wouldn’t!  We hadn’t given you much documentation, and we carefully hid the little bit of doc we did give you. Sorry about that; there is more doc. now (see my other post) and I hear we’re going to post more obvious links soon. Also, we’re being more diligent about signing up to watch bugs so that we can catch these situations.

Deferred

When a bug is closed as Deferred, that means it has been deferred for the current release, not forever. As planning for the next release starts up, management considers the deferred bugs. Some will be selected, and the rest will be retired.  You can decrease the chances that a bug will get retired by voting and commenting on it.  The comments should involve things such as the use case(s), an idea of how often people will run into the issue, and why the suggested workaround (if any) is insufficient. Note that writing in ALL CAPS and adding !!lots of exclamation points!! may be effective in conveying your emotion, but won’t do much to convince management to open the bug. A retired bug will probably never get fixed. No bug should simply be deferred over and over.

External

When a bug is closed as External, that means it’s in some other product.  It may affect Flex applications, but it is not a bug in the actual SDK and will not be tracked in the Flex bug database. This could be at Adobe (e.g. Flash Player bugs) or at another company (e.g. web browser bugs). Usually the other bug database is private, so you won’t be able to look up the status of the other bug. Sorry! You can add a comment requesting an update, and if one of us sees the comment (hopefully we’ve signed up to get email when comments are made…) we’ll go look it up and tell you the status if we can.

Finally, be sure to sign up to watch your bugs. That way you’ll be sure to get email as it moves through the process, as we ask for information, etc…

Best,

– Rob

Posted in Flex Bug Database (Jira) | Leave a Comment »

Flex bug database documentation

Posted by rvollmar on February 15, 2009

In a recent meeting, it seemed that some community members were frustrated about not knowing our bug workflow.  Some basic information has been available, but it’s a little hard to find.  Information has been added, and here are direct links:

The main page: https://bugs.adobe.com/confluence/display/ADOBE/Home

The bug life cycle: https://bugs.adobe.com/confluence/display/ADOBE/Bug+life+cycle

The other way to get this page is to go to http://bugs.adobe.com/flex and then click on the “bug standards/community process” link.

Hope it helps!

– Rob

Posted in Flex Bug Database (Jira) | Leave a Comment »