November 26th, 2007 by Kyle
Posted in: Flex, Flex Builder, Flex Data Services

I just recently was made aware that there are actually 3 different “builds” of Flex SDK “hotfix 3″ out there.
1. Originally hotfix 3 was applied to hotfix 2 (updating a few swcs) - version 1
2. Late summer 2007 it was realized this confused some folks so the hotfix kb article was replaced with a full version of the SDK with the fixes applied - version 2
3. Flex Builder 3 beta 2 shipped with the latest/greatest SDK from the 2.0.1 branch which is an equivalent to hotfix 3 SDK - version 3.

These versions should be functionally identical afaik.

I updated my version checker to detect and differentiate these versions. I have updated the original blog entry here and also have links to the update AIR app here.


No Comments »

November 26th, 2007 by Kyle
Posted in: Flex

This is a follow on to my previous blog entry:
http://blog.739saintlouis.com/2007/11/22/flex-linebreaks-in-the-datagrid/

Here I show how to deal with line breaks in itemRenderer and itemEditors instead of in a datagrid labelFunction.
(This is also a nice example of writing simple, separate itemRenderer and itemEditors.)

Here is the application code:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:local="*">

    <mx:Array id="arr2">
        <mx:Object articleName="Finding out a characters \nUnicode character code \nDownloading the latest Adobe Labs version \nof Flex 3 SDK/Flex Builder 3 \n(codename: Moxie)" data="15" />
        <mx:Object articleName="Setting an icon in an Alert control" data="14" />
        <mx:Object articleName="Setting an icon in a Button control" data="13" />
        <mx:Object articleName="Installing the latest nightly \nFlex 3 SDK build into Flex Builder 3" data="10" />
        <mx:Object articleName="Detecting which button a user pressed to dismiss an Alert dialog" data="9" />
        <mx:Object articleName="Using the Alert control\nFormatting data tips in a Slide\n" data="8" />
        <mx:Object articleName="Finding out a characters \nUnicode character code \nDownloading the latest Adobe Labs version \nof Flex 3 SDK/Flex Builder 3 \n(codename: Moxie)" data="15" />
        <mx:Object articleName="Setting an icon in an Alert control" data="14" />
        <mx:Object articleName="Setting an icon in a Button control" data="13" />
        <mx:Object articleName="Installing the latest nightly \nFlex 3 SDK build into Flex Builder 3" data="10" />
        <mx:Object articleName="Detecting which button a user pressed to dismiss an Alert dialog" data="9" />
        <mx:Object articleName="Using the Alert control\nFormatting data tips in a Slide\n" data="8" />
        <mx:Object articleName="Finding out a characters \nUnicode character code \nDownloading the latest Adobe Labs version \nof Flex 3 SDK/Flex Builder 3 \n(codename: Moxie)" data="15" />
        <mx:Object articleName="Setting an icon in an Alert control" data="14" />
        <mx:Object articleName="Setting an icon in a Button control" data="13" />
        <mx:Object articleName="Installing the latest nightly \nFlex 3 SDK build into Flex Builder 3" data="10" />
        <mx:Object articleName="Detecting which button a user pressed to dismiss an Alert dialog" data="9" />
        <mx:Object articleName="Using the Alert control\nFormatting data tips in a Slide\n" data="8" />       
    </mx:Array>
    <mx:ArrayCollection id="arrColl2" source="{arr2}" />     

    <mx:DataGrid height="250" dataProvider="{arrColl2}" variableRowHeight="true" width="60%" editable="true">
        <mx:columns>
            <mx:DataGridColumn
                headerText="Name of the article in question"                
                itemRenderer="MyRenderer" dataField="articleName"
                itemEditor="MyEditor" editable="true"
                editorUsesEnterKey="true" />
            <mx:DataGridColumn dataField="data" headerText="ID of the article" editable="false"/>
        </mx:columns>
    </mx:DataGrid>
</mx:Application>
 

Here is the itemRenderer based on Text:

<?xml version="1.0" encoding="utf-8"?>
<mx:Text xmlns:mx="http://www.adobe.com/2006/mxml" text="{txt}"
    implements="mx.controls.listClasses.IDropInListItemRenderer">
<mx:Script>
    <![CDATA[
        import mx.controls.listClasses.ListData;
        import mx.controls.dataGridClasses.DataGridListData;
        import mx.controls.listClasses.BaseListData;

        private var _listData:DataGridListData;          
   
        [Bindable]
        public var txt:String;

        override public function set data(value:Object):void {
            super.data = value;   
            var str:String = data[_listData.dataField];
            var myPattern:RegExp = /\\n/g; 
            var newStr:String=str.replace(myPattern, "\n");
            txt = newStr;
        }

        override public function get data():Object {
            return super.data;
        }           
       
     override public function get listData():BaseListData
        {
            return _listData;
        }
   
        override public function set listData(value:BaseListData):void
        {
            _listData = DataGridListData(value);
        }   
   
    ]]>
    </mx:Script>
</mx:Text> 
 

Here is the itemEditor based on TextArea:

<?xml version="1.0" encoding="utf-8"?>
<mx:TextArea xmlns:mx="http://www.adobe.com/2006/mxml" text="{txt}"
    implements="mx.controls.listClasses.IDropInListItemRenderer">
<mx:Script>
    <![CDATA[
        import mx.controls.listClasses.ListData;
        import mx.controls.dataGridClasses.DataGridListData;
        import mx.controls.listClasses.BaseListData;

        private var _listData:DataGridListData;          
   
        [Bindable]
        public var txt:String;

        override public function set data(value:Object):void {
            super.data = value;   
            var str:String = data[_listData.dataField];
            var myPattern:RegExp = /\\n/g; 
            var newStr:String=str.replace(myPattern, "\n");
            txt = newStr;
        }

        override public function get data():Object {
            return super.data;
        }           
       
     override public function get listData():BaseListData
        {
            return _listData;
        }
   
        override public function set listData(value:BaseListData):void
        {
            _listData = DataGridListData(value);
        }   
   
    ]]>
    </mx:Script>
</mx:TextArea>
 

Browse the source of this example.
Download a zipfile containing the source to this sample.

This movie requires Flash Player 9


No Comments »

November 22nd, 2007 by Kyle
Posted in: Flex

This is a follow up to my previous linebreak post.

This demonstrates how to deal with parsing linebreaks when they are in the text data for a datagrid.
You can either escape them in your source text data as shown in the previous post or you can use a labelFunction and some simple regular expression parsing to handle the escaping.

Here is the application code:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
   
    <mx:Script>
        <![CDATA[
        private function format(item:Object, column:DataGridColumn):String{
            var str:String=item[column.dataField].toString();
            var myPattern:RegExp = /\\n/g; 
            var newStr:String=str.replace(myPattern, "\n");
            return newStr;
        }
        ]]>
    </mx:Script>
   
    <mx:Array id="arr1">
        <mx:Object articleName="Finding out a characters \nUnicode character \ncode" data="15" />
        <mx:Object articleName="Setting an icon in an Alert control" data="14" />
        <mx:Object articleName="Setting an icon in a Button control" data="13" />
        <mx:Object articleName="Installing the latest nightly \nFlex 3 SDK build into Flex Builder 3" data="10" />
        <mx:Object articleName="Detecting which button a user pressed to dismiss an Alert dialog" data="9" />
        <mx:Object articleName="Using the Alert control" data="8" />
        <mx:Object articleName="Formatting data tips in a Slider" data="7" />
        <mx:Object articleName="Downloading the latest Adobe Labs version of Flex 3 SDK/Flex Builder 3 (codename: Moxie)" data="6" />
    </mx:Array>
    <mx:ArrayCollection id="arrColl" source="{arr1}" />   
    <mx:Array id="arr2">
        <mx:Object articleName="Finding out a characters {’\n‘}Unicode character code" data="15" />
        <mx:Object articleName="Setting an icon in an Alert control" data="14" />
        <mx:Object articleName="Setting an icon in a Button control" data="13" />
        <mx:Object articleName="Installing the latest nightly {’\n‘}Flex 3 SDK build into Flex Builder 3" data="10" />
        <mx:Object articleName="Detecting which button a user pressed to dismiss an Alert dialog" data="9" />
        <mx:Object articleName="Using the Alert control" data="8" />
        <mx:Object articleName="Formatting data tips in a Slider" data="7" />
        <mx:Object articleName="Downloading the latest Adobe Labs version of Flex 3 SDK/Flex Builder 3 (codename: Moxie)" data="6" />
    </mx:Array>
    <mx:ArrayCollection id="arrColl2" source="{arr2}" />     

    <mx:Text text="this dg uses a labelFunction to manipulate the linebreaks"/>

    <mx:DataGrid id="dataGrid" dataProvider="{arrColl}" variableRowHeight="true" width="60%" height="35%">
        <mx:columns>
            <mx:DataGridColumn labelFunction="format" dataField="articleName" headerText="Name of the article in question"/>
            <mx:DataGridColumn dataField="data" headerText="ID of the article" />
        </mx:columns>
    </mx:DataGrid>   

    <mx:Text text="this dg has the linebreaks modified in the source {’\n‘}arraycollection using curly braces and single quotes."/>

    <mx:DataGrid dataProvider="{arrColl2}" variableRowHeight="true" width="60%" height="35%">
        <mx:columns>
            <mx:DataGridColumn dataField="articleName" headerText="Name of the article in question"/>
            <mx:DataGridColumn dataField="data" headerText="ID of the article" />
        </mx:columns>
    </mx:DataGrid>
</mx:Application>
 

Browse the source of this example.
Download a zipfile containing the source to this sample.

This movie requires Flash Player 9


No Comments »

November 19th, 2007 by Kyle
Posted in: Flex, actionscript, mxml

I had a customer who was having problems with linebreaks in her Flex code.
I had used linebreaks before with no problem until I realized that she was setting text with linebreaks in mxml and not setting properties dynamically as I had done in all instances in teh past when dealing with linebreaks.
I search the Adobe public bugbase and found this bug:

http://bugs.adobe.com/jira/browse/SDK-12649

I thought I’d write a simple app to demonstrate the problem and workarounds.

Here is the source for the app:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
    <mx:Label id="ta1" height="75" width="250" text="This does not \nwrap"/>
    <mx:Button label="click to set via actionscript" click="ta2.text=’Setting via actionscript and\nthis does wrap’"/>
    <mx:Label id="ta2" height="75" width="250"/>
    <mx:Label id="ta3" height="75" width="250" text="Alternatively with this workaround,{’\n‘}this wraps too"/>
</mx:Application>
 

Browse the source of this example.
Download a zipfile containing the source to this sample.

This movie requires Flash Player 9


No Comments »

November 15th, 2007 by Kyle
Posted in: Flex

Here is a sample demonstrating how to dynamically create tabs but maintain the currently selected tab.

Application:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
    xmlns:tabNavigatorTest="tabNavigatorTest.*">

    <mx:Script>
        <![CDATA[
            import mx.core.Container;
           
            private function setTabSelectedIndex(selectedIndex:Number = 0):void{
                trace("before selected index = " + myTab.selectedIndex);
                myTab.selectedIndex = selectedIndex;
                trace("after selected index = " + myTab.selectedIndex);
            }
           
            private function resetTabChildren():void{

                myTab.removeAllChildren();
                addIndex.maximum=0;
                addChildToTabAtIndex(0,0);       
                addChildToTabAtIndex(1,1);
                addChildToTabAtIndex(2,2);               
                               
            }
       
            private function addChildToTabAtIndex(childType:int,index:int):void{
                var childToAdd:Object;
                switch(childType){
                    case 0 :    childToAdd = new Page1();
                                break;
                    case 1 :    childToAdd = new Page2();
                                break;
                    case 2 :    childToAdd = new Page3();
                                break;
                }
                myTab.addChildAt(childToAdd as DisplayObject,index);
                addIndex.maximum++;;               
            }         
           
        ]]>
    </mx:Script>
    <mx:VBox width="100%" height="100%">
        <mx:HBox>
            <!– adjust selectedindex.value - 1 to account for 0 based index –>       
            <mx:Button click="setTabSelectedIndex(tabSelectedIndex.value-1)" label="Set tab selected index"/>
            <mx:NumericStepper id="tabSelectedIndex" minimum="1" maximum="3" value="1"/>
            <!– adjust selectedindex.value - 1 to account for 0 based index –>
            <mx:Button click="addChildToTabAtIndex(tabSelectedIndex.value-1,addIndex.value-1 )">
                <mx:label><![CDATA[<-add tab child Page Type - at position->]]></mx:label>
            </mx:Button>
            <mx:NumericStepper id="addIndex" minimum="1" maximum="1" value="1"/>                       
        </mx:HBox>
   
        <mx:TabNavigator id="myTab" creationComplete="resetTabChildren()"
                width="100%" height="100%" creationPolicy="all" backgroundColor="#FFFFFF"
                borderThickness="1" borderStyle="solid" minHeight="0" minWidth="0"
                selectedTabTextStyleName="selectdTab"
                >
        </mx:TabNavigator>
        <mx:Button click="setTabSelectedIndex(0);callLater(resetTabChildren)" label="reset tab children"/>         
    </mx:VBox>
   
</mx:Application>

 

Here is 1 of three similar children:

<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="400" height="300" label="First Page">
    <mx:Label text="first page"/>
</mx:Canvas>

 

Browse the source of this example.
Download a zipfile containing the source to this sample.

This movie requires Flash Player 9


No Comments »

November 12th, 2007 by Kyle
Posted in: Flex, Flex Data Services

Finding out what version of the SDK you are using for Flex Builder, command line compilation, Ant compilation or in your Flex war file for FDS or LCDS can be comfusing. Especially if you have added one of the SDK hotfixes for 2.0.1. When faced with issues from customers, I often ask them what version of the Flex SDK or FDS/LCDS they are using. Sometimes they don’t know or don’t remember if they have installed a hot fix or if they are running FDS or LCDS. To be fair though, finding out what version of the SDK is not clear nor is finding out the version of a FDS/LCDS war. Cracking open some swc files or jar files to find a build number or starting your server to look for a build number in the output or logs and translating the build number to an actual version equivalent really could be made easier. I thought this would make a good AIR application, so I started coding and here is what I came up with. Mind you, it is not feature complete, pretty looking or by any means architecturally elegant. It does the job though…those other things can come later. This is build with Adobe Air Beta2, which can be downloaded here.

Here is a link to the installer.


1 Comment »

November 12th, 2007 by Kyle
Posted in: Flex

What if you have a datagrid that is only going to have a few rows of data, but the rows have variable height and you want to show all of your rows without a vertical scrollbar?

Here is what:

The app:

<?xml version="1.0"?>
<!– DataGrid control example. –>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" width="550" xmlns="*">

    <mx:Script>

        <![CDATA[
            import mx.controls.Alert;
            import mx.collections.ArrayCollection;
           
            private function createDG():void{
                var myc:MyComp=new MyComp();
                myc.gridData=employees;
                pnl.addChild(myc);
            }
           
            [Bindable]
            private var employees:ArrayCollection = new ArrayCollection([
                {name:"Christina Coenraets", phone:"555-219-2270", email:"ccoenraets@fictitious.com" , active: "true"},
                {name:"Joanne Wall", phone:"555-219-2012", email:"jwall@fictitious.com" , active: "true"},
                {name:"Maurice Smith", phone:"555-219-2012", email:"maurice@fictitious.com" , active: "false"},
                {name:"Mary Jones", phone:"555-219-2000", email:"mjones@fictitious.com", active: "true"}
                                       
            ]);           
        ]]>

    </mx:Script>

    <mx:Button label="Create DG" click="createDG()"/>
    <mx:Panel id="pnl" title="DataGrid Control Example" height="100%" width="100%"
        paddingTop="10" paddingLeft="10" paddingRight="10">
       
    </mx:Panel>
</mx:Application>
 

The component extending datagrid functionality:

<?xml version="1.0" encoding="utf-8"?>
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml">
    <mx:Script>
        <![CDATA[
            import mx.collections.ArrayCollection;

            [Bindable]
            public var text:String = "";   

            [Bindable]
            public var gridData:ArrayCollection;
           
            public function handleCreationComplete(e:Event):void
            {
                trace("finished");
                //+2 for 1 pixel border at top and bottom
                dg.height=dg.measureHeightOfItems(0,gridData.length)+dg.headerHeight+2;
            }
        ]]>
    </mx:Script>
    <mx:DataGrid id="dg"
        editable="true" variableRowHeight="true" width="460"
        dataProvider="{gridData}" creationComplete="handleCreationComplete(event)">
            <mx:columns>
                <mx:DataGridColumn dataField="name" headerText="Name"/>
                <mx:DataGridColumn dataField="phone" headerText="Phone"/>
                <mx:DataGridColumn dataField="email" headerText="Email"/>
            </mx:columns>
        </mx:DataGrid> 
</mx:VBox>
 

Browse the source of this example.
Download a zipfile containing the source to this sample.

This movie requires Flash Player 9


No Comments »

November 9th, 2007 by Kyle
Posted in: Flex, mxml

Apparently this is something that happened in Flex 1.5 by default or was easily settable. It wasn’t too difficult in the Flex 2.x codebase, but I thought I’d post the solution anyways.

Here is the sample app:

<?xml version="1.0"?>
<!– Simple example to demonstrate the MenuBar control. –>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="initCollections();">
    <mx:Script>
        <![CDATA[
            import mx.controls.menuClasses.IMenuBarItemRenderer;
            import mx.controls.MenuBar;
            import mx.controls.menuClasses.MenuBarItem;

            import mx.events.MenuEvent;
            import mx.controls.Alert;
            import mx.collections.*;
           

            [Bindable]
            public var menuBarCollection:XMLListCollection;
   
            private var menubarXML:XMLList =
                <>
                    <menuitem label="Menu1" data="top">
                        <menuitem label="MenuItem 1-A" data="1A"/>
                        <menuitem label="MenuItem 1-B" data="1B"/>
                    </menuitem>
                    <menuitem label="Menu2" data="top">
                        <menuitem label="MenuItem 2-A" type="check"  data="2A"/>
                        <menuitem type="separator"/>
                        <menuitem label="MenuItem 2-B" >
                            <menuitem label="SubMenuItem 3-A" type="radio"
                                groupName="one" data="3A"/>
                            <menuitem label="SubMenuItem 3-B" type="radio"
                                groupName="one" data="3B"/>
                        </menuitem>
                    </menuitem>
                    <menuitem label="Menu3" data="top">
                        <menuitem label="MenuItem 3-A" data="3A"/>
                        <menuitem label="MenuItem 3-B" data="3B"/>
                    </menuitem>
                    <menuitem label="Menu4" data="top">
                        <menuitem label="MenuItem 4-A" data="4A"/>
                        <menuitem label="MenuItem 4-B" data="4B"/>
                    </menuitem>                                       
                </>;

            // Event handler to initialize the MenuBar control.
            private function initCollections():void {
                menuBarCollection = new XMLListCollection(menubarXML);
            }

            // Event handler for the MenuBar control’s itemClick event.
            private function menuHandler(event:MenuEvent):void  {
                // Don’t open the Alert for a menu bar item that
                // opens a popup submenu.
                if (event.item.@data != "top") {
                    Alert.show("Label: " + event.item.@label + "\n" +
                        "Data: " + event.item.@data, "Clicked menu item");
                }       
            }
           
            private function onTopSelection(event:MenuEvent):void{
                var mb:MenuBar=event.target as MenuBar;
                var selectedIndex:int=mb.selectedIndex;
   
                for (var i:int=0;i<mb.menuBarItems.length;i++){
                    if(i==selectedIndex){
                        (mb.menuBarItems[i] as MenuBarItem).setStyle("fontWeight","bold");               
                    }
                    else{
                        (mb.menuBarItems[i] as MenuBarItem).setStyle("fontWeight","normal");                           
                    }
                }
            }
           
         ]]>
    </mx:Script>

    <mx:Panel title="MenuBar Control Example" height="75%" width="75%"
        paddingTop="10" paddingLeft="10">

        <mx:Label width="100%" color="blue"
           text="Select a menu item."/>

        <mx:MenuBar labelField="@label" itemClick="menuHandler(event);"
            dataProvider="{menuBarCollection}" change="onTopSelection(event)" />
           
    </mx:Panel>
</mx:Application>
 

Browse the source of this example.
Download a zipfile containing the source to this sample.

This movie requires Flash Player 9


No Comments »

November 6th, 2007 by Kyle
Posted in: Flex, actionscript

Here is another good datagrid itemrender that I refer to when starting on datagrid renderer issues for customers.
It demonstrates how to create an itemEditor that is based on VBox and has child components (in this case a checkbox) and demonstrates how to implement the IDropInListItemRenderer and IFocusManagerComponent interfaces.
The sample also demonstrates how to add a listener to the underlying dataprovider arraycollection to detect change events and show what data has changed when edits are committed to the collection.

Here is the code for the application:

<?xml version="1.0"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="init()">
    <mx:Script>
        <![CDATA[
            import mx.events.CollectionEvent;
            import mx.events.DataGridEventReason;
            import mx.collections.ArrayCollection;
            import mx.events.DataGridEvent;
            import mx.events.ListEvent;
       
            [Bindable]
            private var myAC:ArrayCollection = new ArrayCollection([
                {id:89, Contact: ‘Bob Jones’, FollowUp: true },
                {id:5, Contact: ‘Jane Smith’, FollowUp: true },   
                {id:7, Contact: ‘Doug Johnson’, FollowUp: false },
                {id:15, Contact: ‘John Jackson’, FollowUp: true },   
                {id:21, Contact: ‘Christina Coenraets’, FollowUp: true },
                {id:4, Contact: ‘Joanne Wall’, FollowUp: false },   
                {id:461, Contact: ‘Maurice Smith’, FollowUp: false },
                {id:35, Contact: ‘Lorraine Barnes’, FollowUp: true },   
                {id:61, Contact: ‘The Dude’, FollowUp: true },
                {id:56, Contact: ‘Abe Rockaway’, FollowUp: