Showing posts with label Flex 4. Show all posts
Showing posts with label Flex 4. Show all posts

Saturday, June 21, 2014

Flex: Different FillMode of the Spark Image Component

The Flex Spark Image component has this interesting property known as 'FillMode' and this should give you a rough idea what each individual type of 'FillMOde' represents.

Source Code for the main application - 'SimpleImageFillMode.mxml'
<?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/mx"
      width="100%"
      height="100%"
      backgroundColor="#CDCDCD">
 <fx:Declarations>
  <!-- Place non-visual elements (e.g., services, value objects) here -->
 </fx:Declarations>
 <fx:Script>
  <![CDATA[
   [Embed(source="assets/avatar.png")]
   [Bindable]
   public var imgClass:Class;
  ]]>
 </fx:Script>
 <s:VGroup width="100%"
     height="100%" 
     horizontalAlign="center" 
     verticalAlign="middle">
  <s:HGroup horizontalAlign="center" 
      verticalAlign="middle">
   <s:HGroup horizontalAlign="center" 
       verticalAlign="middle"
       width="150">
    <s:Label text="Original Image"/>
   </s:HGroup>
   <s:HGroup horizontalAlign="center" 
       verticalAlign="middle"
       width="450">
    <s:Image source="{imgClass}" 
       width="100" 
       height="100"/>
   </s:HGroup>
  </s:HGroup>
  <s:HGroup horizontalAlign="center" 
      verticalAlign="middle">
   <s:HGroup width="150"/>
   <s:HGroup horizontalAlign="center" 
       verticalAlign="middle"
       width="150">
    <s:Label text="Fill Mode: clip"/>
   </s:HGroup>
   <s:HGroup horizontalAlign="center" 
       verticalAlign="middle"
       width="150">
    <s:Label text="Fill Mode: repeat"/>
   </s:HGroup>
   <s:HGroup horizontalAlign="center" 
       verticalAlign="middle"
       width="150">
    <s:Label text="Fill Mode: scale"/>
   </s:HGroup>
  </s:HGroup>
  <s:HGroup horizontalAlign="center" 
      verticalAlign="middle">
   <s:HGroup horizontalAlign="center" 
       verticalAlign="middle"
       width="150">
    <s:Label text="Size (80 * 80)"/>
   </s:HGroup>
   <s:HGroup horizontalAlign="center" 
       verticalAlign="middle"
       width="150">
    <s:Image source="{imgClass}"
       width="80"
       height="80"
       fillMode="clip"/>
   </s:HGroup>
   <s:HGroup horizontalAlign="center" 
       verticalAlign="middle"
       width="150">
    <s:Image source="{imgClass}"
       width="80"
       height="80"
       fillMode="repeat"/>
   </s:HGroup>
   <s:HGroup horizontalAlign="center" 
       verticalAlign="middle"
       width="150">
    <s:Image source="{imgClass}"
       width="80"
       height="80"
       fillMode="scale"/>
   </s:HGroup>
  </s:HGroup>
  <s:HGroup horizontalAlign="center" 
      verticalAlign="middle">
   <s:HGroup horizontalAlign="center" 
       verticalAlign="middle"
       width="150">
    <s:Label text="Size (100 * 150)"/>
   </s:HGroup>
   <s:HGroup horizontalAlign="center" 
       verticalAlign="middle"
       width="150">
    <s:Image source="{imgClass}"
       width="100"
       height="150"
       fillMode="clip"/>
   </s:HGroup>
   <s:HGroup horizontalAlign="center" 
       verticalAlign="middle"
       width="150">
    <s:Image source="{imgClass}"
       width="100"
       height="150"
       fillMode="repeat"/>
   </s:HGroup>
   <s:HGroup horizontalAlign="center" 
       verticalAlign="middle"
       width="150">
    <s:Image source="{imgClass}"
       width="100"
       height="150"
       fillMode="scale"/>
   </s:HGroup>
  </s:HGroup>
  <s:HGroup horizontalAlign="center" 
      verticalAlign="middle">
   <s:HGroup horizontalAlign="center" 
       verticalAlign="middle"
       width="150">
    <s:Label text="Size (150 * 100)"/>
   </s:HGroup>
   <s:HGroup horizontalAlign="center" 
       verticalAlign="middle"
       width="150">
    <s:Image source="{imgClass}"
       width="150"
       height="100"
       fillMode="clip"/>
   </s:HGroup>
   <s:HGroup horizontalAlign="center" 
       verticalAlign="middle"
       width="150">
    <s:Image source="{imgClass}"
       width="150"
       height="100"
       fillMode="repeat"/>
   </s:HGroup>
   <s:HGroup horizontalAlign="center" 
       verticalAlign="middle"
       width="150">
    <s:Image source="{imgClass}"
       width="150"
       height="100"
       fillMode="scale"/>
   </s:HGroup>
  </s:HGroup>
  <s:HGroup horizontalAlign="center" 
      verticalAlign="middle">
   <s:HGroup horizontalAlign="center" 
       verticalAlign="middle"
       width="150">
    <s:Label text="Size (150 * 150)"/>
   </s:HGroup>
   <s:HGroup horizontalAlign="center" 
       verticalAlign="middle"
       width="150">
    <s:Image source="{imgClass}"
       width="150"
       height="150" 
       fillMode="clip"/>
   </s:HGroup>
   <s:HGroup horizontalAlign="center" 
       verticalAlign="middle"
       width="150">
    <s:Image source="{imgClass}"
       width="150"
       height="150"
       fillMode="repeat"/>
   </s:HGroup>
   <s:HGroup horizontalAlign="center" 
       verticalAlign="middle"
       width="150">
    <s:Image source="{imgClass}"
       width="150"
       height="150"
       fillMode="scale"/>
   </s:HGroup>
  </s:HGroup>
 </s:VGroup>
</s:Application>
* Click here for the demo shown in this post.
^ Click here for the source files for the demo.

Sunday, June 15, 2014

Flex: Hiding the border on a side of a Group...

In flex 4, the style 'boderSides' has been taken out, but there's another way to hide the border of a selected side of a box away. And here's a simple example to give you a rough idea on how to get it done. :)

Source Code for the main application - 'SimpleSelectedBorderExample.mxml'
<?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/mx" 
      creationComplete="creationCompleteEvent(event)" xmlns:Container="Container.*">
 <fx:Script>
  <![CDATA[
   import Container.SimpleGroup;
   
   import mx.events.FlexEvent;
   
   protected function creationCompleteEvent(e:FlexEvent):void
   {
    var tempBox:SimpleGroup;
    for(var i:int = 0; i < 8; i ++){
     for(var j:int = 0; j < 8; j ++){
      tempBox = new SimpleGroup();
      tempBox.x = i * 50 - 0.5;
      tempBox.y = j * 50 - 0.5;
      container.addElement(tempBox);
     } 
    }
   }
  ]]>
 </fx:Script>
 <s:BorderContainer width="100%"
        height="100%" 
        borderVisible="false">
  <s:layout>
   <s:VerticalLayout verticalAlign="middle"
         horizontalAlign="center"/>
  </s:layout>
  <!-- All the boxes will appear inside this container -->
  <s:BorderContainer width="400"
         height="400"
         id="container"
         borderVisible="false"/>
 </s:BorderContainer>      
</s:Application>
Source Code for the Group Class that we are using to repeat the pattern - 'SimpleGroup.mxml'
<?xml version="1.0" encoding="utf-8"?>
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009" 
   xmlns:s="library://ns.adobe.com/flex/spark" 
   xmlns:mx="library://ns.adobe.com/flex/mx" 
   width="50" 
   height="50" 
   creationComplete="creationCompleteEvent(event)">
 <fx:Script>
  <![CDATA[
   import mx.events.FlexEvent;
   
   //Are we going to show the left border?
   [Bindable]
   private var _boolLeft:Boolean = false;
   
   //Are we going to show the right border?
   [Bindable]
   private var _boolRight:Boolean = false;
   
   //Are we going to show the top border?
   [Bindable]
   private var _boolTop:Boolean = false;
   
   //Are we going to show the bottom border?
   [Bindable]
   private var _boolBottom:Boolean = false;
   
   //-1 = border is outside the box
   //-0.5 = border is in the middle
   //0 = border is inside the box
   [Bindable]
   private var _typeValue:Number = 0;
   
   //Thickness of the border
   [Bindable]
   private var _borderThickness:Number = 0;
   
   //Color of the border
   [Bindable]
   private var _borderColor:uint = 0x333333;
   
   protected function creationCompleteEvent(e:FlexEvent):void
   {
    //Randomized the showing and hiding of the borders 
    var rand:Number = Math.round(Math.random());
    if(rand == 1){
     _boolLeft = true;
    }
    rand = Math.round(Math.random());
    if(rand == 1){
     _boolRight = true;
    }
    rand = Math.round(Math.random());
    if(rand == 1){
     _boolTop = true;
    }
    rand = Math.round(Math.random());
    if(rand == 1){
     _boolBottom = true;
    }
    
    _typeValue = Math.round(Math.random() * 2);
    if(_typeValue == 1){
     _typeValue = -0.5;
    }else if(_typeValue == 2){
     _typeValue = -1;
    }
    
    _borderThickness = Math.round(Math.random() * 2) + 1;
    
    _typeValue = _typeValue * _borderThickness;
   }
  ]]>
 </fx:Script>
 <!-- Left -->
 <s:Line left="{_typeValue}"
   top="{_typeValue}"
   bottom="{_typeValue}" 
   visible="{_boolLeft}">
  <s:stroke>
   <s:SolidColorStroke weight="{_borderThickness}"
         color="{_borderColor}"/>
  </s:stroke>
 </s:Line>
 <!-- Bottom -->
 <s:Line left="{_typeValue}"
   right="{_typeValue}"
   bottom="{_typeValue}"
   visible="{_boolBottom}">
  <s:stroke>
   <s:SolidColorStroke weight="{_borderThickness}"
        color="{_borderColor}"/>
  </s:stroke>
 </s:Line>
 <!-- Right -->
 <s:Line right="{_typeValue}"
   top="{_typeValue}"
   bottom="{_typeValue}"
   visible="{_boolRight}">
  <s:stroke>
   <s:SolidColorStroke weight="{_borderThickness}"
        color="{_borderColor}"/>
  </s:stroke>
 </s:Line>
 <!-- Top -->
 <s:Line left="{_typeValue}"
   right="{_typeValue}"
   top="{_typeValue}"
   visible="{_boolTop}">
  <s:stroke>
   <s:SolidColorStroke weight="{_borderThickness}"
        color="{_borderColor}"/>
  </s:stroke>
 </s:Line>
</s:Group>
* Click here for the demo shown in this post.
^ Click here for the source files for the demo.

Friday, May 23, 2014

Flex: Showing and Hiding the Origins of a chart

There might be cases where you wanted to show or replace the vertical and horizontal origin's of the chart with a different type of line. Here's a simple example to demo the hiding and showing of the origin of the chart..

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" 
    layout="absolute" 
    creationComplete="completeHandler(event)">
 <mx:Script>
  <![CDATA[
   import mx.charts.HitData;
   import mx.charts.series.LineSeries;
   import mx.collections.ArrayCollection;
   import mx.collections.Sort;
   import mx.collections.SortField;
   import mx.events.FlexEvent;
   import mx.events.ListEvent;
   import mx.formatters.DateFormatter;
   
   //Records used in the chart
   [Bindable]
   private var myData:XML = 
    <records>
     <record>
      <x>-7.81</x>
      <y>-4.98</y>
     </record>
     <record>
      <x>-2.84</x>
      <y>-4.62</y>
     </record>
     <record>
      <x>-8.66</x>
      <y>2.52</y>
     </record>
     <record>
      <x>3.56</x>
      <y>6.86</y>
     </record>
     <record>
      <x>-9.54</x>
      <y>-8.05</y>
     </record>
     <record>
      <x>7.48</x>
      <y>0.37</y>
     </record>
     <record>
      <x>9.2</x>
      <y>9.5</y>
     </record>
     <record>
      <x>9.32</x>
      <y>-1.59</y>
     </record>
     <record>
      <x>1.77</x>
      <y>-0.86</y>
     </record>
     <record>
      <x>-8.61</x>
      <y>-1.75</y>
     </record>
    </records>;
   
   private var dateCollection:ArrayCollection;
   
   protected function completeHandler(event:FlexEvent):void
   {
    // Parsing the xml data into ArrayCollection
    var objArray:ArrayCollection = new ArrayCollection();
    var tempObj:Object;
    for(var i:int = 0; i < myData.record.length(); i ++)
    {
     tempObj = new Object();
     tempObj.x = myData.record[i].x;
     tempObj.y = myData.record[i].y;
     objArray.addItem(tempObj);
    }
    
    // Create the new series and set its properties.
    var localSeries:LineSeries = new LineSeries();
    localSeries.dataProvider = objArray;
    localSeries.yField = "y";
    localSeries.xField = "x";
    
    // Back up the current series on the chart.
    var currentSeries:Array = mainChart.series;
    // Add the new series to the current Array of series.
    currentSeries.push(localSeries);
    // Add the new Array of series to the chart.
    mainChart.series = currentSeries;
   }
   
   //We are customizing the datatip / tool tip of the
   //chart data.
   public function myDataTipFunction(e:HitData):String {
    var s:String = "";
    s += "x: " + e.item.x + "<br>";
    s += "y: " + e.item.y;
    return s;
   }
  ]]>
 </mx:Script>
 <mx:VBox verticalGap="5" width="100%" height="100%" 
    verticalAlign="middle">
  <mx:HBox width="100%" horizontalAlign="center">
   <mx:LineChart id="mainChart" 
        showDataTips="true" 
        width="95%"
        dataTipFunction="myDataTipFunction">
    <mx:Stroke weight="2" 
         alpha="1" 
         color="#00FF00" 
         id="horiOriginStroke"/>
    <mx:Stroke weight="2" 
         alpha="1" 
         color="#FF0000" 
         id="vertOriginStroke"/>
    <mx:backgroundElements>
     <mx:GridLines direction="both"
          horizontalShowOrigin="{chkHori.selected}"
          horizontalOriginStroke="{horiOriginStroke}" 
          verticalShowOrigin="{chkVert.selected}"
          verticalOriginStroke="{vertOriginStroke}"/>
    </mx:backgroundElements>
   </mx:LineChart>
  </mx:HBox>
  <mx:HBox width="100%"
     horizontalAlign="center">
   <mx:CheckBox id="chkHori" 
       selected="true"       
       label="Show Horizontal Origin"/>
   <mx:CheckBox id="chkVert" 
       selected="true" 
       label="Show Vertical Origin"/>   
  </mx:HBox>
 </mx:VBox>
</mx:Application>
* Click here for the demo shown in this post.
^ Click here for the source files for the demo.

Saturday, March 22, 2014

Flex 4: Accessing the renderers of a DataGroup

There might be situations where you might be creating a list of items in a horizontal or vertical manner. And you might be using a <DataGroup> to get things done. But after you have successfully created a list, you might have to disable 1 of the items, but how are you going to access the individual items of the <DataGroup>? I hope that this post would give an idea on how do access the individual item of a <DataGroup>.

Source Code for the main application - 'SimpleDataGroup.mxml'
<?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/mx" 
      width="100%" 
      height="100%" 
      creationComplete="creationCompleteEvent(event)">
 <fx:Script>
  <![CDATA[
   import events.RendererEvent;
   
   import mx.collections.ArrayCollection;
   import mx.events.FlexEvent;
   
   import renderers.HorizontalRenderer;
   import renderers.VerticalRenderer;
   
   private var dataArray:Array = [{
    label: 'Item 1',
    value: 'A'
   },{
    label: 'Item 2',
    value: 'B'
   },{
    label: 'Item 3',
    value: 'C'
   },{
    label: 'Item 4',
    value: 'D'
   },{
    label: 'Item 5',
    value: 'E'
   },{
    label: 'Item 6',
    value: 'F'
   },{
    label: 'Item 7',
    value: 'G'
   },{
    label: 'Item 8',
    value: 'H'
   }];
   
   //Our Data
   [Bindable]
   private var dataCollection:ArrayCollection = 
    new ArrayCollection(dataArray);
   
   //This will be our simple result text string.
   [Bindable]
   private var resultStr:String = "";
   
   protected function creationCompleteEvent(event:FlexEvent):void
   {
    this.addEventListener(RendererEvent.RENDERER_CLICK_EVENT,
     clickEvent);
   }
   
   //Upon clicking on one of the buttons, we will loop through
   //all the buttons in the DataGroup and change their state
   //accordingly.
   private function clickEvent(event:RendererEvent):void
   {
    var tempHRenderer:HorizontalRenderer;
    var tempVRenderer:VerticalRenderer;
    for(var i:int = 0; i < hData.numElements; i ++)
    {
     tempHRenderer = 
      HorizontalRenderer(hData.getElementAt(i));
     if(tempHRenderer.data.label == event.label)
     {
      tempHRenderer.currentState = "selected";
     }else{
      tempHRenderer.currentState = "init";
     }
    }
    for(i = 0; i < vData.numElements; i ++)
    {
     tempVRenderer = 
      VerticalRenderer(vData.getElementAt(i));
     if(tempVRenderer.data.label == event.label)
     {
      tempVRenderer.currentState = "click";
      resultStr = "You have click on the button " +
       "labeled '" + tempVRenderer.data.label + 
       "' with a value of '" + 
       tempVRenderer.data.value + "'";
     }else{
      tempVRenderer.currentState = "norm";
     } 
    }
   }
  ]]>
 </fx:Script>
 <s:VGroup width="100%" 
     height="100%" 
     horizontalAlign="center" 
     verticalAlign="middle">
  <s:Label text="Try clicking on a button."/>
  <s:DataGroup width="100%" 
      id="hData"
      dataProvider="{dataCollection}"
      itemRenderer="renderers.HorizontalRenderer">
   <s:layout>
    <s:HorizontalLayout gap="0" 
         verticalAlign="middle" 
         horizontalAlign="center"/>
   </s:layout>
  </s:DataGroup>
  <s:DataGroup width="100%"
      id="vData"
      dataProvider="{dataCollection}"
      itemRenderer="renderers.VerticalRenderer">
   <s:layout>
    <s:VerticalLayout gap="0"
          verticalAlign="middle" 
          horizontalAlign="center"/>
   </s:layout>
  </s:DataGroup>
  <s:Label text="{resultStr}"/>
 </s:VGroup>
</s:Application>

And here's the custom event class for the renderers - 'RendererEvent.as'
package events
{
 import flash.events.Event;
 
 public class RendererEvent extends Event
 {
  //We will dispatch this event when we 
  //click on a renderer.
  public static const RENDERER_CLICK_EVENT:String = 
   "RenderClickEvent";
  
  //Used to stores the label 
  public var label:String = "";
  
  public function RendererEvent
   (type:String, 
    bubbles:Boolean=false, 
    cancelable:Boolean=false, 
    _label:String="")
  {
   super(type, bubbles, cancelable);
   label = _label;
  }
  
  override public function clone():Event
  {
   return new RendererEvent(type, 
    false, 
    false, 
    label);
  }
 }
}

And here's the horizontal item renderer - 'HorizontalRenderer.mxml'
<?xml version="1.0" encoding="utf-8"?>
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:s="library://ns.adobe.com/flex/spark" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    autoDrawBackground="true" 
    mouseChildren="false" 
    click="clickHandler(event)" 
    buttonMode="true">
 
 <fx:Script>
  <![CDATA[
   import events.RendererEvent;
   
   //When we click on this Renderer, 
   //we will dispatch an event.
   protected function clickHandler(event:MouseEvent):void
   {
    this.dispatchEvent(
     new RendererEvent(
      RendererEvent.RENDERER_CLICK_EVENT, 
      true, 
      false, 
      this.data.label));
   }
  ]]>
 </fx:Script>
 <s:states>
  <s:State name="init"/>
  <s:State name="selected"/>
 </s:states>
 <s:BorderContainer height="30" 
        width="80">
  <s:backgroundFill.init>
   <s:LinearGradient rotation="90">
    <s:GradientEntry color="0xFFFFFF"/>
    <s:GradientEntry color="0xCCCCCC"/>
   </s:LinearGradient>
  </s:backgroundFill.init>
  <s:backgroundFill.selected>
   <s:LinearGradient rotation="90">
    <s:GradientEntry color="0xFFFFCC"/>
    <s:GradientEntry color="0xCCFF99"/>
   </s:LinearGradient>
  </s:backgroundFill.selected>
  <s:borderStroke> 
   <mx:SolidColorStroke 
    color="black" 
    weight="1"/> 
  </s:borderStroke>
  <s:VGroup width="100%" 
      height="100%"
      horizontalAlign="center"
      verticalAlign="middle">
   <s:Label text="{data.label}"
      color="0x000000"/>
  </s:VGroup>
 </s:BorderContainer>
</s:ItemRenderer>

And here's the vertical item renderer - 'VerticalRenderer.mxml'
<?xml version="1.0" encoding="utf-8"?>
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:s="library://ns.adobe.com/flex/spark" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    autoDrawBackground="true" 
    mouseChildren="false" 
    click="clickHandler(event)" 
    buttonMode="true">
 
 <fx:Script>
  <![CDATA[
   import events.RendererEvent;
   
   //When we click on this Renderer, 
   //we will dispatch an event.
   protected function clickHandler(event:MouseEvent):void
   {
    this.dispatchEvent(
     new RendererEvent(
      RendererEvent.RENDERER_CLICK_EVENT, 
      true, 
      false, 
      this.data.label));
   }
  ]]>
 </fx:Script>
 <s:states>
  <s:State name="norm"/>
  <s:State name="click"/>
 </s:states>
 <s:BorderContainer height="30" 
        width="80">
  <s:backgroundFill.norm>
   <s:LinearGradient rotation="90">
    <s:GradientEntry color="0xCCCCCC"/>
    <s:GradientEntry color="0x666666"/>
   </s:LinearGradient>
  </s:backgroundFill.norm>
  <s:backgroundFill.click>
   <s:LinearGradient rotation="90">
    <s:GradientEntry color="0xCCFFFF"/>
    <s:GradientEntry color="0x00FFCC"/>
   </s:LinearGradient>
  </s:backgroundFill.click>
  <s:borderStroke> 
   <mx:SolidColorStroke 
    color="black" 
    weight="1"/> 
  </s:borderStroke>
  <s:VGroup width="100%" 
      height="100%" 
      horizontalAlign="center" 
      verticalAlign="middle">
   <s:Label text="{data.label}"
      color.norm="0xFFFFFF"
      color.click="0x000000"/>
  </s:VGroup>
 </s:BorderContainer>
</s:ItemRenderer>
* Click here for the demo shown in this post.
^ Click here for the source files for the demo.

Friday, January 17, 2014

Problems with special characters on the web...

Sometimes when I was writing or editing a post on my blog, I'm encountering numerous situations where a ' or a " can mess up your contents when you publish it. The same problem also occur when I'm creating the asdocs for flex projects. If you have entered > or < characters not as a html node but part of your text, you might have problems creating the asdocs.

After look through numerous sites, I think that 'HTML entities' is one of
the better alternatives for Encoding and Decoding HTML Entities. On top of
that, it has also provided a list that shows all the special characters
and the corresponding HTML Entities.

* Click here for the website 'HTML Entities'.
^ Click here for my previous post on how to create asdocs for your flex projects.

Friday, January 3, 2014

Flex: JSON Deserialization

JSON a much shorter and faster response as compared to XML. Therefore, although some third party api out there still gives you the option of returning the results in XML format, it also gives you the option of getting the results in JSON format too. So I'm just doing up a simple JSON Deserialization example. :D

Main Application Class - SimpleJSONDeserialize.mxml
<?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/mx">
 <fx:Declarations>
  <s:HTTPService url="http://maps.googleapis.com/maps/api/geocode/json" 
        method="GET" 
        concurrency="single" 
        useProxy="false" 
        id="httpService" 
        result="httpServiceResultEvent(event)" 
        fault="httpServiceFaultEvent(event)">
   <s:request xmlns="">
    <address>{txtInput.text}</address>
    <sensor>false</sensor>
   </s:request>
  </s:HTTPService>
 </fx:Declarations>
 <fx:Script>
  <![CDATA[
   import com.adobe.serialization.json.JSON;
   
   import model.MapResult;
   import model.MapServiceResult;
   
   import mx.collections.ArrayCollection;
   import mx.rpc.events.FaultEvent;
   import mx.rpc.events.ResultEvent;
   
   import org.osflash.vanilla.Vanilla;
   
   private var mapResult:MapServiceResult;
   
   [Bindable]
   private var resultCollection:ArrayCollection;
   
   //Upon clicking on the button, we will trigger the request
   protected function searchBtnClickHandler(event:MouseEvent):void
   {
    httpService.send();
   }
   
   //Upon making a successful request
   protected function httpServiceResultEvent(event:ResultEvent):void
   {
    //Converts the json result to a Object.
    var tempJSONObject:Object = JSON.decode(String(event.result));
    
    //Converts the Object into a Object of class type MapServiceResult
    mapResult = new Vanilla().extract(tempJSONObject, MapServiceResult);
    
    //Since we couldn't bind a Vector to a Datagrid directly,
    //we will just push the results to a ArrayCollection and
    //bind it to a DataGrid.
    resultCollection = new ArrayCollection();
    for each(var item:MapResult in mapResult.results)
    {
     resultCollection.addItem(item);
    }
    resultCollection.refresh();
   }
   
   //Upon making a failure request
   protected function httpServiceFaultEvent(event:FaultEvent):void
   {
   }
  ]]>
 </fx:Script>
 <s:VGroup width="100%" 
     height="100%" 
     verticalAlign="middle" 
     horizontalAlign="center">
  <s:Label text="Please enter an address:"/>
  <s:HGroup horizontalAlign="center">
   <s:TextInput id="txtInput"/>
   <s:Button label="Search Now!" 
       id="searchBtn" 
       click="searchBtnClickHandler(event)"/>
  </s:HGroup>
  <s:DataGrid dataProvider="{resultCollection}" 
     width="400" 
     height="300">
   <s:columns>
    <s:ArrayList>
     <s:GridColumn headerText="Formatted Address"
          dataField="formattedAddress"/>
    </s:ArrayList>
   </s:columns>
  </s:DataGrid>
 </s:VGroup>
</s:Application>

Model class for HttpServiceResults - MapServiceResult.as
package model
{
 public class MapServiceResult
 {
  public var status:String;
  private var _results: Vector.;

  public function get results():Vector.
  {
   return _results;
  }

  /**
   * Vanilla class will handle all these mapping, hence
   * it will map the object results into the Vector
   * of type MapResult.
   * 
   * But when we are getting a empty string rather than
   * an Array, we will have to handle such a condition 
   */
  public function set results(value:*):void
  {
   _results = new Vector.;
   if(String(value) != "")
   {
    _results = value; 
   }
  }
 }
}

Model class for individual Result - MapResult.as
package model
{
 public class MapResult
 {
  //Vanilla will map all the values of 
  //address_components into the Vector 
  //addrComponents.
  [Marshall (field="address_components")]
  public var addrComponents: Vector.;
  [Marshall (field="formatted_address")]
  public var formattedAddress:String;
  public var types: Vector.;
 }
}

Model class for individual address_components - AddrComponents.as
package model
{
 public class AddrComponents
 {
  //Vanilla will map the value of the field 
  //long_name to longName 
  [Marshall (field="long_name")]
  public var longName:String;
  [Marshall (field="short_name")]
  public var shortName:String;
  public var types: Vector.;
 }
}
* Click here for the source files for the demo.
  (This requires a valid Google Geocoding API key, but currently it will work if you
  are running it locally.)
^ Click here to find out more about the Vanilla as3 library.
~ Click here to find out more about the as3corelib.

Tuesday, October 15, 2013

Flex: XML appending

How to append a new node into a XML object in Flex/as3? Here's a simple example that teaches you how to append a XML node. Here's a guide on how to do it. But do take note that you have to use either _ or a letter for the first character of the name of the new node that you are trying to insert. However if you want to use numbers for the first character, there's a way to do it too. :P Besides for the ways that I have listed in this post, you can use dot notation (.) to append a new node too. :)

Source Code for the main application - 'SimpleXMLManipulation.mxml'
<?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/mx" 
      creationComplete="creationCompleteEvt(event)" 
      xmlns:local="*">
 <fx:Declarations>
  <local:SimpleXMLConverter id="converter"/>
 </fx:Declarations>
 <fx:Script>
  <![CDATA[
   import mx.events.FlexEvent;
   
   protected function creationCompleteEvt(e:FlexEvent):void
   {
    converter.init();
   }
  ]]>
 </fx:Script>
 <s:VGroup width="100%" 
     height="100%" 
     verticalAlign="middle" 
     horizontalAlign="center">
  <s:Label text="Original XML"/>
  <s:TextArea text="@{converter.simpleXML}"/>
  <s:Spacer height="10"/>
  <s:HGroup>
   <s:VGroup horizontalAlign="center">
    <s:Label text="Modified XML using appendChild()"/>
    <s:TextArea text="{converter.simpleXML1}" 
       editable="false"
        width="30%" 
       minWidth="300"/>  
   </s:VGroup>
   <s:VGroup horizontalAlign="center">
    <s:Label text="Modified XML using []"/>
    <s:TextArea text="{converter.simpleXML2}"
       editable="false"
       width="30%" 
       minWidth="300"/>   
   </s:VGroup>
  </s:HGroup>
 </s:VGroup>
</s:Application>

Source code for the XML manipulating class
package
{
 import flash.events.Event;
 import flash.events.EventDispatcher;
 
 [Bindable]
 public class SimpleXMLConverter extends EventDispatcher
 {
  //XML String
  private var simpleXMLString:String = "" +
   "";
  
  //XML that contains the above simpleXMLString
  private var _simpleXML:XML;
  
  [Bindable(event="simpleXMLChanged")]
  public function get simpleXML():String
  {
   return _simpleXML;
  }

  public function set simpleXML(value:String):void
  {
   //If the input value isn't a valid XML,
   //we will set it to empty.
   try
   {
    _simpleXML = XML(value);
   }catch(e:Error)
   {
    _simpleXML = new XML();
   }
   
   //Modified XML using appendChild()
   simpleXML1 = XML(_simpleXML.toXMLString());
   if(simpleXML1)
   {
    var dummyXMLNode:XML;
    var dummyXMLNodeStr:String;
    dummyXMLNodeStr = "<" + name1Str + name2Str + ">";
    dummyXMLNodeStr += valueStr;
    dummyXMLNodeStr += "";
    dummyXMLNode = new XML(dummyXMLNodeStr);
    simpleXML1.appendChild(dummyXMLNode);
    if(simpleXML1.level1.length() > 0)
    {
     for(var i:int = 0; i < simpleXML1.level1.length(); i ++)
     {
      simpleXML1.level1[i].appendChild(dummyXMLNode);
     }
    }
   }
   
   //Modified XML using []
   simpleXML2 = XML(_simpleXML.toXMLString());
   if(simpleXML2)
   {
    simpleXML2[name1Str + name2Str] = 
     valueStr;
    if(simpleXML2.level1.length() > 0)
    {
     for(i = 0; i < simpleXML2.level1.length(); i ++)
     {
      simpleXML2.level1[i][name1Str + name2Str] = 
       valueStr;
     }
    }
   }
   
   //dispatching the 8 event to update the
   //respective text area
   dispatchEvent(new Event("simpleXML1Changed", 
    true, true));
   dispatchEvent(new Event("simpleXML2Changed", 
    true, true));
  }
  
  //XML that contains the modified XML based
  //on the above simpleXMLString and appendChild()
  private var _simpleXML1:XML;

  public function get simpleXML1():XML
  {
   return _simpleXML1;
  }

  [Bindable(event="simpleXML1Changed")]
  public function set simpleXML1(value:XML):void
  {
   _simpleXML1 = value;
  }
  
  //XML that contains the modified XML based
  //on the above simpleXMLString and []
  private var _simpleXML2:XML;

  public function get simpleXML2():XML
  {
   return _simpleXML2;
  }
  
  [Bindable(event="simpleXML2Changed")]
  public function set simpleXML2(value:XML):void
  {
   _simpleXML2 = value;
  }
  
  //The name of the empty node - part1
  private var name1Str:String = "empty";
  //The name of the empty node - part2
  private var name2Str:String = "node";
  
  //The value of the empty node
  private var valueStr:String = "dummyValue";
  
  public function init():void
  {
   simpleXML = new XML(simpleXMLString);
   
   //dispatching the event to update the main
   //respective text area
   dispatchEvent(new Event("simpleXMLChanged", 
    true, true));
  }
 }
}
* Click here for the demo shown in this post.
^ Click here for the source files for the demo.

Saturday, October 5, 2013

Flex 4: Disabling a Button Bar Button...

I was trying to disable one of the buttons that belongs to a 'Button Bar' component that comes with Flex 4. After spending a bit of time debugging and googling, I finally managed to come out with a decent solution to it...

Source Code for the main application - 'SimpleButtonBarEnabling.mxml'
<?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/mx" 
      creationComplete="creationCompleteEvent(event)">
 <fx:Script>
  <![CDATA[
   import mx.events.FlexEvent;
   
   protected function creationCompleteEvent(event:FlexEvent):void
   {
    //We are disabling the 4th button.
    otherInfo.enabled = false;
   }
   
  ]]>
 </fx:Script>
 <s:VGroup width="100%" 
     height="100%"
     verticalAlign="middle" 
     horizontalAlign="center" 
     gap="0">
  <!-- Create a Spark ButtonBar control to navigate 
   the ViewStack container. -->
  <s:ButtonBar dataProvider="{myViewStack}" 
      skinClass="CustomButtonBarSkin"/>
  
  <!-- Define the ViewStack and the three 
   child containers. -->
  <mx:ViewStack id="myViewStack" 
       borderStyle="solid" 
       width="50%"
       paddingBottom="10"
       paddingTop="10"
       paddingLeft="10"
       paddingRight="10">  
   <s:NavigatorContent id="search" 
       label="Search">
    <s:Label text="Search Screen"/>
   </s:NavigatorContent>
  
   <!-- set enabled="false" to disable the button -->
   <s:NavigatorContent id="custInfo" 
       label="Customer Info" 
       enabled="false">
    <s:Label text="Customer Info"/>
   </s:NavigatorContent>
  
   <s:NavigatorContent id="accountInfo" 
       label="Account Info">
    <s:Label text="Account Info"/>
   </s:NavigatorContent>
   
   <s:NavigatorContent id="otherInfo" 
        label="Others">
    <s:Label text="Others"/>
   </s:NavigatorContent>
  </mx:ViewStack>  
 </s:VGroup>
</s:Application>
And here's the custom skin class for the 'Button Bar' component.
<?xml version="1.0" encoding="utf-8"?>

<!--

    ADOBE SYSTEMS INCORPORATED
    Copyright 2008 Adobe Systems Incorporated
    All Rights Reserved.

    NOTICE: Adobe permits you to use, modify, and distribute this file
    in accordance with the terms of the license agreement accompanying it.

-->

<!--- The default skin class for the Spark ButtonBar component. The buttons on the ButtonBar component
    use the ButtonBarLastButtonSkin, ButtonBarFirstButtonSkin and ButtonBarMiddleButtonSkin classes.  
    
      @see spark.components.ButtonBar
      @see spark.components.ButtonBarButton    
        
      @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[ 
       /** 
         * @copy spark.skins.spark.ApplicationSkin#hostComponent
         */
        [HostComponent("spark.components.ButtonBar")]
    ]]>
    </fx:Metadata> 

    <s:states>
        <s:State name="normal" />
        <s:State name="disabled" />
    </s:states>
    
    <fx:Declarations>

  <!--- Have removed the first and third button since it's not needed.  -->
  
        <!--- 
            @copy spark.components.ButtonBar#middleButton
            @default spark.skins.spark.ButtonBarMiddleButtonSkin
            @see spark.skins.spark.ButtonBarMiddleButtonSkin
  
   The middle Button will be used as the item renderer for all the
   buttons of this button bar. And we are enabling the buttons
   base on the data passed into this component.
        -->
        <fx:Component id="middleButton" >
            <s:ButtonBarButton enabled="{data.enabled}"/>
        </fx:Component>

    </fx:Declarations>

    <!--- @copy spark.components.SkinnableDataContainer#dataGroup -->
    <s:DataGroup id="dataGroup" width="100%" height="100%">
        <s:layout>
            <s:ButtonBarHorizontalLayout gap="-1"/>
        </s:layout>
    </s:DataGroup>

</s:Skin>
* Click here for the demo shown in this post.
^ Click here for the source files for the demo.

Thursday, September 19, 2013

Flex 4: Using Ant to create a smaller file size like bin-release

I was trying to create an automation script for some of the projects in Adobe Flex 4 the other day and I realised that the ant build is generating a far more bigger swf file (in terms of the file size)than the ones created using bin-release. After numerous attempts, I finally managed to compress the file size to match the ones that that were generated using bin-release.

<!-- Within the <mxmlc> tag of your ant script, you need to 
 add the following. And take note of the comments below -->
<mxmlc>
 <static-link-runtime-shared-libraries>false</static-link-runtime-shared-libraries>

 <runtime-shared-library-path path-element="${FLEX_HOME}/frameworks/libs/textLayout.swc">
  <!-- If you are copying and pasting, do take note that 
   'textLayout_1.0.0.595.swz' isn't in the 'flex/' folder 
   but the 'tlf/' folder under 
   'http://fpdownload.adobe.com/pub/swz/' -->
  <url rsl-url="http://fpdownload.adobe.com/pub/swz/tlf/1.0.0.595/textLayout_1.0.0.595.swz" 
   policy-file-url="http://fpdownload.adobe.com/pub/swz/crossdomain.xml"/>
  <url rsl-url="textLayout_1.0.0.595.swz" policy-file-url="" />
 </runtime-shared-library-path>

 <!-- If you are copying and pasting, do take note that 
  'framework.swc' needs to be included before the other 'swz' 
  that belongs to the same 'flex/' folder under 
  'http://fpdownload.adobe.com/pub/swz/', otherwise errors
  will occur when you run the web application. -->
    <runtime-shared-library-path path-element="${FLEX_HOME}/frameworks/libs/framework.swc">
        <url rsl-url="http://fpdownload.adobe.com/pub/swz/flex/4.5.0.20967/framework_4.5.0.20967.swz" 
   policy-file-url="http://fpdownload.adobe.com/pub/swz/crossdomain.xml"/>
        <url rsl-url="framework_4.0.0.14159.swz" policy-file-url="" />
    </runtime-shared-library-path>

    <runtime-shared-library-path path-element="${FLEX_HOME}/frameworks/libs/spark.swc">
  <url rsl-url="http://fpdownload.adobe.com/pub/swz/flex/4.5.0.20967/spark_4.5.0.20967.swz" 
   policy-file-url="http://fpdownload.adobe.com/pub/swz/crossdomain.xml"/>
  <url rsl-url="spark_4.0.0.14159.swz" policy-file-url="" />
 </runtime-shared-library-path>

 <runtime-shared-library-path path-element="${FLEX_HOME}/frameworks/libs/sparkskins.swc">
  <url rsl-url="http://fpdownload.adobe.com/pub/swz/flex/4.5.0.20967/sparkskins_4.5.0.20967.swz" 
   policy-file-url="http://fpdownload.adobe.com/pub/swz/crossdomain.xml"/>
  <url rsl-url="sparkskins_4.0.0.14159.swz" policy-file-url="" />
 </runtime-shared-library-path>

 <runtime-shared-library-path path-element="${FLEX_HOME}/frameworks/libs/rpc.swc">
  <url rsl-url="http://fpdownload.adobe.com/pub/swz/flex/4.5.0.20967/rpc_4.5.0.20967.swz" 
   policy-file-url="http://fpdownload.adobe.com/pub/swz/crossdomain.xml"/>
  <url rsl-url="rpc_4.0.0.14159.swz" policy-file-url="" />
 </runtime-shared-library-path>

 <runtime-shared-library-path path-element="${FLEX_HOME}/frameworks/libs/charts.swc">
  <url rsl-url="http://fpdownload.adobe.com/pub/swz/flex/4.5.0.20967/charts_4.5.0.20967.swz" 
   policy-file-url="http://fpdownload.adobe.com/pub/swz/crossdomain.xml"/>
  <url rsl-url="charts_4.5.0.20967.swz" policy-file-url="" />
 </runtime-shared-library-path>

 <!-- If you are copying and pasting, do take note that 'mx.swc'
  isn't in the 'libs/' folder but the 'libs/mx/' folder under 
  '${FLEX_HOME}/frameworks/libs/'  -->
 <runtime-shared-library-path path-element="${FLEX_HOME}/frameworks/libs/mx/mx.swc">
  <url rsl-url="http://fpdownload.adobe.com/pub/swz/flex/4.5.0.20967/mx_4.5.0.20967.swz" 
   policy-file-url="http://fpdownload.adobe.com/pub/swz/crossdomain.xml"/>
  <url rsl-url="mx_4.5.0.20967.swz" policy-file-url="" />
 </runtime-shared-library-path>
</mxmlc>
* Click here for a great guide on creating the ant automation file for your flex 4 project.

Friday, September 13, 2013

Flex: Scrolling to a particular row of data of a Datagrid

I was looking for a much more easier way of scrolling to a particular row of data that belongs to the dataGrid. And I managed to find this.

Source Code for the main application - 'SimpleDataGridScrolling.mxml'
<?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/mx" >
 <fx:Declarations>
  <fx:XMLList id="records">
   <record>
    <id>01</id>
    <name>Eric</name>
    <address>3987 Mauris Rd.</address>
   </record>
   <record>
    <id>02</id>
    <name>Bradley</name>
    <address>692-535 Id Street</address>
   </record>
   <record>
    <id>03</id>
    <name>Flynn</name>
    <address>191-491 Ullamcorper Road</address>
   </record>
   <record>
    <id>04</id>
    <name>Akeem</name>
    <address>400-2992 Donec Rd.</address>
   </record>
   <record>
    <id>05</id>
    <name>Shad</name>
    <address>P.O. Box 490, 9377 Lorem, Avenue</address>
   </record>
   <record>
    <id>06</id>
    <name>Brady</name>
    <address>P.O. Box 203, 418 Amet Street</address>
   </record>
   <record>
    <id>07</id>
    <name>Igor</name>
    <address>5584 Ultrices Av.</address>
   </record>
   <record>
    <id>08</id>
    <name>Herman</name>
    <address>Ap #316-3329 Fermentum Avenue</address>
   </record>
   <record>
    <id>09</id>
    <name>Martin</name>
    <address>932-8151 Arcu. Road</address>
   </record>
   <record>
    <id>10</id>
    <name>Micah</name>
    <address>P.O. Box 244, 8472 Lacus. Ave</address>
   </record>
   <record>
    <id>11</id>
    <name>Isaiah</name>
    <address>3798 Risus. Avenue</address>
   </record>
   <record>
    <id>12</id>
    <name>Amos</name>
    <address>Ap #377-2082 Mollis. Road</address>
   </record>
   <record>
    <id>13</id>
    <name>Dominic</name>
    <address>P.O. Box 801, 2289 Malesuada Rd.</address>
   </record>
   <record>
    <id>14</id>
    <name>Ethan</name>
    <address>Ap #509-2519 Non, Avenue</address>
   </record>
   <record>
    <id>15</id>
    <name>Julian</name>
    <address>9373 Ut Avenue</address>
   </record>
   <record>
    <id>16</id>
    <name>Yoshio</name>
    <address>120-7486 Ornare, Av.</address>
   </record>
   <record>
    <id>17</id>
    <name>Harlan</name>
    <address>Ap #821-3336 Velit. Av.</address>
   </record>
   <record>
    <id>18</id>
    <name>Rigel</name>
    <address>Ap #689-7263 Consectetuer Rd.</address>
   </record>
   <record>
    <id>19</id>
    <name>Holmes</name>
    <address>Ap #790-6923 Tincidunt St.</address>
   </record>
   <record>
    <id>20</id>
    <name>Aidan</name>
    <address>948-115 Imperdiet Street</address>
   </record>
   <record>
    <id>21</id>
    <name>Colin</name>
    <address>P.O. Box 454, 9501 Lectus Avenue</address>
   </record>
   <record>
    <id>22</id>
    <name>Palmer</name>
    <address>Ap #402-1566 Varius Road</address>
   </record>
   <record>
    <id>23</id>
    <name>Sylvester</name>
    <address>852-8076 Enim. St.</address>
   </record>
   <record>
    <id>24</id>
    <name>Cole</name>
    <address>876-4551 Ornare Ave</address>
   </record>
   <record>
    <id>25</id>
    <name>Yardley</name>
    <address>P.O. Box 256, 4107 Tempor Rd.</address>
   </record>
   <record>
    <id>26</id>
    <name>Coby</name>
    <address>P.O. Box 467, 7273 Nulla Street</address>
   </record>
   <record>
    <id>27</id>
    <name>Beau</name>
    <address>743-8871 Sem Rd.</address>
   </record>
   <record>
    <id>28</id>
    <name>Kermit</name>
    <address>Ap #183-8772 Magna. St.</address>
   </record>
   <record>
    <id>29</id>
    <name>Josiah</name>
    <address>P.O. Box 645, 453 Ornare, St.</address>
   </record>
   <record>
    <id>30</id>
    <name>Elijah</name>
    <address>537 Turpis Avenue</address>
   </record>
  </fx:XMLList>
  <s:XMLListCollection id="tempXmlCollection" 
        source="{records}"/>
  <s:XMLListCollection id="tempXmlCollection1" 
        source="{records.id}"/>
 </fx:Declarations>
 <fx:Script>
  <![CDATA[
   import mx.events.FlexEvent;
   
   import spark.components.List;
   import spark.events.IndexChangeEvent;
   
   /**
    * Upon changing the selection of the drop down menu,
    * we would need to loop through the data of the
    * datagrid and find the one that matches the 
    * selection from the drop down menu and we would
    * select the row and scroll to that row.
    */
   protected function changeHandler(event:IndexChangeEvent):void
   {
    var tempData:Object = ddId.selectedItem;
    var tempDP:XMLListCollection = 
     gridData.dataProvider as XMLListCollection;
    for(var i:int = 0; i < tempDP.length; i ++)
    {
     if(tempDP.getItemAt(i).id == tempData)
     {
      gridData.selectedIndex = i;
      //This works in Flex 4 Spark Components.
      gridData.grid.verticalScrollPosition = 
       gridData.grid.getCellY(i, 0);
      //This works in Flex 3 Components but not 
      //for Spark Components.
      //gridData.scrollToIndex(i);
      break;
     }
    }
   }
   
  ]]>
 </fx:Script>
 <s:VGroup verticalAlign="middle" 
     horizontalAlign="center" 
     width="100%" 
     height="100%">
  <s:HGroup verticalAlign="middle" 
      horizontalAlign="center" >
   <s:Label text="Select a ID:"/>
   <s:DropDownList id="ddId"
       dataProvider="{tempXmlCollection1}"
       change="changeHandler(event)"/>
  </s:HGroup>
  <s:DataGrid id="gridData" 
     height="200"
      width="500"
     resizableColumns="true"
     dataProvider="{tempXmlCollection}">
   <s:columns>
    <s:ArrayList>
     <s:GridColumn dataField="id" 
          minWidth="50"
          headerText="ID"/>
     <s:GridColumn dataField="name" 
          minWidth="150"
          headerText="Name"/>
     <s:GridColumn dataField="address"  
          minWidth="280" 
          headerText="Address"/>
    </s:ArrayList>
   </s:columns>
  </s:DataGrid>
 </s:VGroup>
</s:Application>
* Click here for the demo shown in this post.
^ Click here for the source files for the demo.

Friday, August 30, 2013

Flex: A Simple Slider with a Labeled Button

Time to move back to the easier stuff. In the older versions of Flex, you would need to play around a few properties and create a few components in order to create a similar UI component. However, in the newer versions of Flex, some sophisticated stuff back then have now been simplified. However that doesn't mean that the development time can reduce greatly, it simply means that you don't need to waste too much time figuring out these small little stuff.

The source codes of the main application file - SimpleSliderWithValue.mxml
<?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/mx">
 <fx:Style source="css/style.css"/>
 <s:HGroup width="100%" 
     height="100%" 
     verticalAlign="middle"
     horizontalAlign="center">
  <s:VSlider minimum="0"
       maximum="100"
       value="50"  
       showDataTip="false" 
       height="200"
       styleName="customSliderV"/>
   <s:HSlider minimum="0"
       maximum="100"
       value="50" 
       showDataTip="false" 
       width="200" 
       styleName="customSliderH"/>
 </s:HGroup>
</s:Application>

Skin Class for the Horizontal Slider - skins/CustomHSliderWithLabel.mxml
<?xml version="1.0" encoding="utf-8"?>

<!--

    ADOBE SYSTEMS INCORPORATED
    Copyright 2008 Adobe Systems Incorporated
    All Rights Reserved.

    NOTICE: Adobe permits you to use, modify, and distribute this file
    in accordance with the terms of the license agreement accompanying it.
-->

<!--- The default skin class for the Spark HSlider component. The thumb and track skins are defined by the
HSliderThumbSkin and HSliderTrackSkin classes, respectively.  

       @see spark.components.HSlider
       @see spark.skins.spark.HSliderThumbSkin
       @see spark.skins.spark.HSliderTrackSkin
                
      @langversion 3.0
      @playerversion Flash 10
      @playerversion AIR 1.5
      @productversion Flex 4
-->
<s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark"
    xmlns:fb="http://ns.adobe.com/flashbuilder/2009" minHeight="11" alpha.disabled="0.5">

    <fx:Metadata>
    <![CDATA[ 
        /** 
         * @copy spark.skins.spark.ApplicationSkin#hostComponent
         */
        [HostComponent("spark.components.HSlider")]
    ]]>
    </fx:Metadata> 
    
    <fx:Script fb:purpose="styling">
        /* Define the skin elements that should not be colorized. 
           For slider, the skin itself is colorized but the individual parts are not. */
        static private const exclusions:Array = ["track", "thumb"];

        /**
         * @private
         */  
        override public function get colorizeExclusions():Array {return exclusions;}
        
        /**
         * @private
         */
        override protected function initializationComplete():void
        {
            useChromeColor = true;
            super.initializationComplete();
        }
    </fx:Script>
    
    <fx:Script>
        /**
         *  @private
         */  
        override protected function measure() : void
        {
            // Temporarily move the thumb to the left of the Slider so measurement
            // doesn't factor in its x position. This allows resizing the
            // HSlider to less than 100px in width. 
            var thumbPos:Number = thumb.getLayoutBoundsX();
            thumb.setLayoutBoundsPosition(0, thumb.getLayoutBoundsY());
            super.measure();
            thumb.setLayoutBoundsPosition(thumbPos, thumb.getLayoutBoundsY());
        }
    </fx:Script>
    
    <s:states>
        <s:State name="normal" />
        <s:State name="disabled" />
    </s:states>
    
    <fx:Declarations>
        <!--- The tooltip used in the mx.controls.Slider control. 
               To customize the DataTip's appearance, create a custom HSliderSkin class.-->
        <fx:Component id="dataTip">     
           <s:DataRenderer minHeight="24" minWidth="40" y="-34">  
              <s:Rect top="0" left="0" right="0" bottom="0">
                    <s:fill>
                        <s:SolidColor color="0x000000" alpha=".9"/>
                    </s:fill>
                    <s:filters>
                        <s:DropShadowFilter angle="90" color="0x999999" distance="3"/>
                    </s:filters>
                </s:Rect>
                <s:Label id="labelDisplay" text="{data}"
                         horizontalCenter="0" verticalCenter="1"
                         left="5" right="5" top="5" bottom="5"
                         textAlign="center" verticalAlign="middle"
                         fontWeight="normal" color="white" fontSize="11">
                </s:Label>
            </s:DataRenderer>
       </fx:Component>
    </fx:Declarations>
    
    <!--- 
   The default skin class is HSliderTrackSkin. 
   @copy spark.components.supportClasses.TrackBase#track
   @see spark.skins.spark.HSliderTrackSkin 
 
   We changing the size of the track so that it will
   become very thin.
 -->
    <s:Button id="track" left="0" right="0" top="8" bottom="8" minWidth="33" width="100" 
              tabEnabled="false"
              skinClass="spark.skins.spark.HSliderTrackSkin" />
              
    <!--- 
   The default skin class is HSliderThumbSkin.
         @copy spark.components.supportClasses.TrackBase#thumb 
         @see spark.skins.spark.HSliderThumbSkin
 
   We changing the Button Skin Class to 
   spark.skins.spark.ButtonSkin so that we 
   can bind the label to the thumb.
 -->
    <s:Button id="thumb" top="0" bottom="0" width="45" height="20" 
              tabEnabled="false" styleName="customSliderHThumb" 
     label="{hostComponent.value}" />
</s:SparkSkin>

Skin Class for the Vertical Slider - skins/CustomVSliderWithLabel.mxml
<?xml version="1.0" encoding="utf-8"?>

<!--

    ADOBE SYSTEMS INCORPORATED
    Copyright 2008 Adobe Systems Incorporated
    All Rights Reserved.

    NOTICE: Adobe permits you to use, modify, and distribute this file
    in accordance with the terms of the license agreement accompanying it.
-->

<!--- The default skin class for the Spark VSlider component. The thumb and track skins are defined by the
VSliderThumbSkin and VSliderTrackSkin classes, respectively.  

       @see spark.components.VSlider
       @see spark.skins.spark.VSliderThumbSkin
       @see spark.skins.spark.VSliderTrackSkin
        
      @langversion 3.0
      @playerversion Flash 10
      @playerversion AIR 1.5
      @productversion Flex 4
-->
<s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark"
    xmlns:fb="http://ns.adobe.com/flashbuilder/2009" minWidth="11" alpha.disabled="0.5">

    <fx:Metadata>
    <![CDATA[ 
        /** 
         * @copy spark.skins.spark.ApplicationSkin#hostComponent
         */
        [HostComponent("spark.components.VSlider")]
    ]]>
    </fx:Metadata> 
    
    <fx:Script fb:purpose="styling">
        /* Define the skin elements that should not be colorized. 
           For slider, the skin itself is colorized but the individual parts are not. */
        static private const exclusions:Array = ["track", "thumb"];

        /**
         * @private
         */   
        override public function get colorizeExclusions():Array {return exclusions;}
        
        /**
         * @private
         */
        override protected function initializationComplete():void
        {
            useChromeColor = true;
            super.initializationComplete();
        }
    </fx:Script>
 
    <fx:Script>
        /**
         *  @private
         */  
        override protected function measure() : void
        {
            // Temporarily move the thumb to the top of the Slider so measurement
            // doesn't factor in its y position. This allows resizing the
            // VSlider to less than 100px in height. 
            var thumbPos:Number = thumb.getLayoutBoundsY();
            thumb.setLayoutBoundsPosition(thumb.getLayoutBoundsX(), 0);
            super.measure();
            thumb.setLayoutBoundsPosition(thumb.getLayoutBoundsX(), thumbPos);
        }
    </fx:Script>
    
    <s:states>
        <s:State name="normal" />
        <s:State name="disabled" />
    </s:states>
    
    <fx:Declarations>
        <!--- The tooltip used in the mx.controls.Slider control.
              To customize the DataTip's appearance, create a custom VSliderSkin class. -->
        <fx:Component id="dataTip">
            <s:DataRenderer minHeight="24" minWidth="40" x="20"> 
                <s:Rect top="0" left="0" right="0" bottom="0">
                    <s:fill>
                        <s:SolidColor color="0x000000" alpha=".9"/>
                    </s:fill>
                    <s:filters>
                        <s:DropShadowFilter angle="90" color="0x999999" distance="3"/>
                    </s:filters>
                </s:Rect>
                <s:Label id="labelDisplay" text="{data}"
                         horizontalCenter="0" verticalCenter="1"
                         left="5" right="5" top="5" bottom="5"
                         textAlign="center" verticalAlign="middle"
                         fontWeight="normal" color="white" fontSize="11">
                </s:Label>
            </s:DataRenderer>
        </fx:Component>
    </fx:Declarations>
    
    <!--- 
   The default skin class is VSliderTrackSkin.
   @copy spark.components.supportClasses.TrackBase#track 
   @see spark.skins.spark.VSliderTrackSkin 
 
   We changing the size of the track so that it will
   become very thin. 
 -->
    <s:Button id="track" left="17" right="17" top="0" bottom="0" minHeight="33" height="100"
              tabEnabled="false"
              skinClass="spark.skins.spark.VSliderTrackSkin" />
              
    <!--- 
   The default skin class is VSliderThumbSkin. 
   @copy spark.components.supportClasses.TrackBase#thumb
   @see spark.skins.spark.VSliderThumbSkin
   
   We changing the Button Skin Class to 
   spark.skins.spark.ButtonSkin so that we 
   can bind the label to the thumb.
 -->
    <s:Button id="thumb" left="0" right="0" width="36" height="27"
              tabEnabled="false" styleName="customSliderVThumb" 
     label="{hostComponent.value}" />
</s:SparkSkin>

The main CSS file - css/style.css
/* CSS file */
@namespace s "library://ns.adobe.com/flex/spark";
@namespace mx "library://ns.adobe.com/flex/mx";

s|VSlider.customSliderV{
 skinClass: ClassReference("skins.CustomVSliderWithLabel");
}
s|HSlider.customSliderH{
 skinClass: ClassReference("skins.CustomHSliderWithLabel");
}
.customSliderHThumb,.customSliderVThumb{
 skinClass: ClassReference("spark.skins.spark.ButtonSkin");
}
* Click here for the demo shown in this post.
^ Click here for the source files for the demo.

Wednesday, August 14, 2013

Flex: Generating ASDoc

Rather than searching high and low for a particular function, wouldn't it be much more easier if you can just search through a set of HTML files in case you need to reference some codes that you have writen back then? Therefore, I have created a ant file to auto generated the HTML for the Flex 3 and Flex 4 projects that I have shown on this blog.

Main Ant file - build.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<project basedir="." default="dist.asdocs">
 <!-- project root directory -->
 <property name="APP_ROOT" location="${basedir}/.." />
 <property file="build.properties" />

 <target name="dist.asdocs" description="Create asdocs">
  <cleanAsdocsDir3 />
  <createAsdocs3 />
  <cleanAsdocsDir4 />
  <createAsdocs4 />
 </target>

 <macrodef name="createAsdocs3">
  <sequential>
      <tstamp prefix="dateStamp">
          <format property="date" pattern="MMM/dd/yyyy hh:mm:ss aa" unit="hour" />
      </tstamp>
   <java taskname="asdoc" jar="${FLEX_HOME_3}/lib/asdoc.jar" 
    failonerror="true" fork="true">
    <jvmarg value="-Dapplication.home=${FLEX_HOME_3}"/>
    <!-- Need to assign lots for memory for the ant job -->
    <jvmarg value="-Dsun.io.useCanonCaches=false"/>
    <jvmarg value="-Xms512m"/>
    <jvmarg value="-Xmx1024m"/>
    <jvmarg value="-XX:MaxPermSize=256m"/>

    <arg value="-warnings=false" />
    <!-- Root directory of files -->
    <arg value="-source-path" />
    <arg value="${APP_ROOT}/../AccessingSWFLoaderFunctions/src" />
    <arg value="${APP_ROOT}/../BubbleEventTest/src" />
    <arg value="${APP_ROOT}/../ClippingContent/src" />
    <arg value="${APP_ROOT}/../CustomiseToolTip/src" />
    <arg value="${APP_ROOT}/../DateCheckerApplication/src" />
    <arg value="${APP_ROOT}/../drawingShapes/src" />
    <arg value="${APP_ROOT}/../FlexCustomPreloader/src" />
    <arg value="${APP_ROOT}/../htmlEntity/src" />
    <arg value="${APP_ROOT}/../LinkList/src" />
    <arg value="${APP_ROOT}/../ListDragAndDrop/src" />
    <arg value="${APP_ROOT}/../MeasurePosition/src" />
    <arg value="${APP_ROOT}/../MultipleViewWithAlivePDF/src" />
    <arg value="${APP_ROOT}/../PlayingWithAlivePDF/src" />
    <arg value="${APP_ROOT}/../PlayingWithAlivePDF/fonts" />
    <arg value="${APP_ROOT}/../PlayingWithRegExp/src" />
    <arg value="${APP_ROOT}/../PopUpOverlay/src" />
    <arg value="${APP_ROOT}/../ScreenCaptureView/src" />
    <arg value="${APP_ROOT}/../SimpleChartHorizontalAxis/src" />
    <arg value="${APP_ROOT}/../SimpleSingleton/src" />
    <arg value="${APP_ROOT}/../stopBubbleEventTest/src" />
    <!-- List of files to document -->
    <arg value="-doc-sources" />
    <arg value="${APP_ROOT}/../AccessingSWFLoaderFunctions/src" />
    <arg value="${APP_ROOT}/../BubbleEventTest/src" />
    <arg value="${APP_ROOT}/../ClippingContent/src" />
    <arg value="${APP_ROOT}/../CustomiseToolTip/src" />
    <arg value="${APP_ROOT}/../DateCheckerApplication/src" />
    <arg value="${APP_ROOT}/../drawingShapes/src" />
    <arg value="${APP_ROOT}/../FlexCustomPreloader/src" />
    <arg value="${APP_ROOT}/../htmlEntity/src" />
    <arg value="${APP_ROOT}/../LinkList/src" />
    <arg value="${APP_ROOT}/../ListDragAndDrop/src" />
    <arg value="${APP_ROOT}/../MeasurePosition/src" />
    <arg value="${APP_ROOT}/../MultipleViewWithAlivePDF/src" />
    <arg value="${APP_ROOT}/../PlayingWithAlivePDF/src" />
    <arg value="${APP_ROOT}/../PlayingWithRegExp/src" />
    <arg value="${APP_ROOT}/../PopUpOverlay/src" />
    <arg value="${APP_ROOT}/../ScreenCaptureView/src" />
    <arg value="${APP_ROOT}/../SimpleChartHorizontalAxis/src" />
    <arg value="${APP_ROOT}/../SimpleSingleton/src" />
    <arg value="${APP_ROOT}/../stopBubbleEventTest/src" />
    <!-- Adding a external library, if u are using one -->
    <arg value="-external-library-path" />
    <arg value="${APP_ROOT}/../PlayingWithAlivePDF/libs" />
    <!-- Title of the generated asdoc webpage -->
    <arg value="-window-title" />
    <arg value="Flex 3.5.0 Projects Documentation" />
    <!-- Header shown in the generated asdoc webpage -->
    <arg value="-main-title" />
    <arg value="Flex 3.5.0 Projects Documentation" />
    <!-- Footer shown in the generated asdoc webpage -->
    <arg value="-footer" />
    <arg value="Created on ${dateStamp.date}" />
    <!-- Output folder of the generated asdoc webpage -->
    <arg value="-output" />
    <arg value="${OUTPUT_DOCS_DIR_3}" />
    <!-- If your project requires some TrueType, OpenType fonts -->
    <!--<arg value="-managers" />
    <arg value="flash.fonts.AFEFontManager" />-->
   </java>
  </sequential>
 </macrodef>

 <macrodef name="cleanAsdocsDir3">
  <sequential>
   <echo message="Clean Asdocs Directory" />
   <delete dir="${OUTPUT_DOCS_DIR_3}" failonerror="false" />
   <mkdir dir="${OUTPUT_DOCS_DIR_3}" />
   <echo>Cleaned asdocs output directory</echo>
  </sequential>
 </macrodef>

 <macrodef name="createAsdocs4">
  <sequential>
      <tstamp prefix="dateStamp">
          <format property="date" pattern="MMM/dd/yyyy hh:mm:ss aa" unit="hour" />
      </tstamp>
   <java taskname="asdoc" jar="${FLEX_HOME_4}/lib/asdoc.jar" 
    failonerror="true" fork="true">
    <jvmarg value="-Dapplication.home=${FLEX_HOME_4}"/>
    <!-- Need to assign lots for memory for the ant job -->
    <jvmarg value="-Dsun.io.useCanonCaches=false"/>
    <jvmarg value="-Xms512m"/>
    <jvmarg value="-Xmx1024m"/>
    <jvmarg value="-XX:MaxPermSize=256m"/>

    <arg value="-warnings=false" />
    <!-- Root directory of files -->
    <arg value="-source-path" />
    <arg value="${APP_ROOT}/../AutoresizableTextfield/src" />
    <arg value="${APP_ROOT}/../ImageSourceIssue/src" />
    <arg value="${APP_ROOT}/../NotReallyGlobalTooltip/src" />
    <arg value="${APP_ROOT}/../OpenURLOfHTMLText/src" />
    <arg value="${APP_ROOT}/../Simple2WayBinding/src" />
    <arg value="${APP_ROOT}/../Simple3StateCheckBox/src" />
    <arg value="${APP_ROOT}/../SimpleAreaChartToolTip/src" />
    <arg value="${APP_ROOT}/../SimpleButtonBarSelect/src" />
    <arg value="${APP_ROOT}/../SimpleChartAnimation/src" />
    <arg value="${APP_ROOT}/../SimpleChartDataClick/src" />
    <arg value="${APP_ROOT}/../SimpleChartPositionOfAPoint/src" />
    <arg value="${APP_ROOT}/../SimpleChartVisibility/src" />
    <arg value="${APP_ROOT}/../SimpleCopyingOfObjects/src" />
    <arg value="${APP_ROOT}/../SimpleDataTipBorder/src" />
    <arg value="${APP_ROOT}/../SimpleDoubleClicking/src" />
    <arg value="${APP_ROOT}/../SimpleMouseReleaseOutside/src" />
    <arg value="${APP_ROOT}/../SimpleMouseReleaseOutside/src" />
    <arg value="${APP_ROOT}/../SimplePastingDetection/src" />
    <arg value="${APP_ROOT}/../SimpleStackingColumn/src" />
    <arg value="${APP_ROOT}/../SimpleSudokuGrid/src" />
    <arg value="${APP_ROOT}/../SimpleTabSequence/src" />
    <arg value="${APP_ROOT}/../SimpleTwitterPost/src" />
    <!-- List of files to document -->
    <arg value="-doc-sources" />
    <arg value="${APP_ROOT}/../AutoresizableTextfield/src" />
    <arg value="${APP_ROOT}/../ImageSourceIssue/src" />
    <arg value="${APP_ROOT}/../NotReallyGlobalTooltip/src" />
    <arg value="${APP_ROOT}/../OpenURLOfHTMLText/src" />
    <arg value="${APP_ROOT}/../Simple2WayBinding/src" />
    <arg value="${APP_ROOT}/../Simple3StateCheckBox/src" />
    <arg value="${APP_ROOT}/../SimpleAreaChartToolTip/src" />
    <arg value="${APP_ROOT}/../SimpleButtonBarSelect/src" />
    <arg value="${APP_ROOT}/../SimpleChartAnimation/src" />
    <arg value="${APP_ROOT}/../SimpleChartDataClick/src" />
    <arg value="${APP_ROOT}/../SimpleChartPositionOfAPoint/src" />
    <arg value="${APP_ROOT}/../SimpleChartVisibility/src" />
    <arg value="${APP_ROOT}/../SimpleCopyingOfObjects/src" />
    <arg value="${APP_ROOT}/../SimpleDataTipBorder/src" />
    <arg value="${APP_ROOT}/../SimpleDoubleClicking/src" />
    <arg value="${APP_ROOT}/../SimpleMouseReleaseOutside/src" />
    <arg value="${APP_ROOT}/../SimpleMouseReleaseOutside/src" />
    <arg value="${APP_ROOT}/../SimplePastingDetection/src" />
    <arg value="${APP_ROOT}/../SimpleStackingColumn/src" />
    <arg value="${APP_ROOT}/../SimpleSudokuGrid/src" />
    <arg value="${APP_ROOT}/../SimpleTabSequence/src" />
    <arg value="${APP_ROOT}/../SimpleTwitterPost/src" />
    <!-- Title of the generated asdoc webpage -->
    <arg value="-window-title" />
    <arg value="Flex 4.6.0 Projects Documentation" />
    <!-- Header shown in the generated asdoc webpage -->
    <arg value="-main-title" />
    <arg value="Flex 4.6.0 Projects Documentation" />
    <!-- Footer shown in the generated asdoc webpage -->
    <arg value="-footer" />
    <arg value="Created on ${dateStamp.date}" />
    <!-- Output folder of the generated asdoc webpage -->
    <arg value="-output" />
    <arg value="${OUTPUT_DOCS_DIR_4}" />
    <!-- If your project requires some TrueType, OpenType fonts -->
    <!--<arg value="-managers" />
    <arg value="flash.fonts.AFEFontManager" />-->
   </java>
  </sequential>
 </macrodef>

 <macrodef name="cleanAsdocsDir4">
  <sequential>
   <echo message="Clean Asdocs Directory" />
   <delete dir="${OUTPUT_DOCS_DIR_4}" failonerror="false" />
   <mkdir dir="${OUTPUT_DOCS_DIR_4}" />
   <echo>Cleaned asdocs output directory</echo>
  </sequential>
 </macrodef>
</project>

Main Ant Properties file - build.properties
# change this to your Flex SDK directory path
FLEX_HOME_3=C:/Program Files (x86)/Adobe/Adobe Flash Builder 4.5/sdks/3.6.0
FLEX_HOME_4=C:/Program Files (x86)/Adobe/Adobe Flash Builder 4.5/sdks/4.5.0

# output location for the asdocs for flex 3.6
OUTPUT_DOCS_DIR_3 = ${APP_ROOT}/../asdocs_3.6

# output location for the asdocs for flex 4.5
OUTPUT_DOCS_DIR_4 = ${APP_ROOT}/../asdocs_4.5
* Click here to find out more about ASDoc.
* Click here for the ASDoc that I have generated for my Flex 3 projects.
* Click here for the ASDoc that I have generated for my Flex 4 projects.
* Click here to download the ant build files that I have shown in this post.

Thursday, August 8, 2013

Flex: Creating a Checkbox with 3 states...

There will be situations that requires a list of checkboxes and you are giving the user the option of selecting and unselecting the individual options. However, the normal checkbox might work for the individual selections but it will not work nicely for the header. Therefore...

Main Application Source Code - Simple3StateCheckBox.mxml
<?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/mx" 
      creationComplete="creationCompleteHandler(event)">
 <fx:Declarations>
  <!-- Place non-visual elements (e.g., services, value objects) here -->
 </fx:Declarations>
 <fx:Style source="css/style.css"/>
 <fx:Script>
  <![CDATA[
   import events.CustomCheckBoxEvents;
   
   import mx.collections.ArrayCollection;
   import mx.events.FlexEvent;
   
   import object.SingletonObject;
   
   /**
    * We are using a singleton object to store the objects/data.
    */
   private var dataObj:SingletonObject = 
    SingletonObject.getInstance();
   /**
    * Upon creationComplete, we need to add all the Listeners
    * and check the appropriate state that we should be
    * displaying for the header.
    */
   protected function creationCompleteHandler(event:FlexEvent):void
   {
    this.addEventListener(
     CustomCheckBoxEvents.SELECT_ALL_ITEMS,
     checkBoxEvent);
    this.addEventListener(
     CustomCheckBoxEvents.UNSELECT_ALL_ITEMS,
     checkBoxEvent);
    this.addEventListener(
     CustomCheckBoxEvents.SELECT_AN_ITEM,
     checkBoxEvent);
    this.addEventListener(
     CustomCheckBoxEvents.UNSELECT_AN_ITEM,
     checkBoxEvent);
    updateHeaderState();
   }
   
   /**
    * All the events are handled over here.
    */
   private function checkBoxEvent(event:CustomCheckBoxEvents):void
   {
    for each(var item:Object in dataObj.expenses)
    {
     if(event.type == CustomCheckBoxEvents.SELECT_ALL_ITEMS)
     {
      item.selected = true;
     }else if(event.type == CustomCheckBoxEvents.UNSELECT_ALL_ITEMS)
     {
      item.selected = false;
     }else if(item.id == event.data.id)
     {
      if(event.type == 
       CustomCheckBoxEvents.SELECT_AN_ITEM)
      {
       item.selected = true;
      }else if(event.type == 
       CustomCheckBoxEvents.UNSELECT_AN_ITEM)
      {
       item.selected = false;
      }
     }
    }
    dataObj.expenses.refresh();
    updateHeaderState();
   }
   
   /**
    * Function to determine that best state that we are
    * showing for the header.
    */
   private function updateHeaderState():void
   {
    var count:Number = 0;
    var maxCount:Number = 0;
    for each(var item:Object in dataObj.expenses)
    {
     maxCount ++;
     if(item.selected)
     {
      count ++;
     }
    }
    if(count == 0)
    {
     dataObj.selectedState = 0;
    }else if(count == maxCount)
    {
     dataObj.selectedState = 2;
    }else{
     dataObj.selectedState = 1;
    }
   }
  ]]>
 </fx:Script>
 <s:VGroup width="100%"
     height="100%" 
     verticalAlign="middle" 
     horizontalAlign="center">
  <s:DataGrid width="50%"
      height="50%" 
     dataProvider="{dataObj.expenses}">
   <s:columns>
    <s:ArrayList>
     <s:GridColumn dataField="selected" 
          width="20"
          headerRenderer="renderers.CustomHeaderCheckBoxRenderer"
          itemRenderer="renderers.CustomCheckBoxRenderer"/>
     <s:GridColumn dataField="amount"/>
    </s:ArrayList>
   </s:columns>
  </s:DataGrid>
 </s:VGroup>
</s:Application>

Event class for the checkbox - events/CustomCheckBoxEvents.as
package events
{
 import flash.events.Event;
 
 public class CustomCheckBoxEvents extends Event
 {
  //All the different event type
  public static const SELECT_ALL_ITEMS:String = 
   "selectAllItems";
  public static const UNSELECT_ALL_ITEMS:String = 
   "unselectAllItems";
  public static const SELECT_AN_ITEM:String = 
   "selectAnItem";
  public static const UNSELECT_AN_ITEM:String = 
   "unselectAnItem";
  
  private var _data:Object = null;

  public function get data():Object
  {
   return _data;
  }

  public function set data(value:Object):void
  {
   _data = value;
  }
  
  public function CustomCheckBoxEvents(type:String, tempData:Object = null, bubbles:Boolean=true, cancelable:Boolean=false)
  {
   super(type, bubbles, cancelable);
   _data = tempData;
  }
  
  override public function clone():Event
  {
   // TODO Auto Generated method stub
   return new CustomCheckBoxEvents(type, data, bubbles, cancelable);
  }
 }
}

Singleton Object class to store the neccessary data - object/SingletonObject.as
package object
{
 import mx.collections.ArrayCollection;

 public class SingletonObject
 {
  private static var _instance:SingletonObject=null;
  
  /**
   * You need the following functions to create a
   * singleton Object. SingletonObject(e:SingletonEnforcer)
   * and getInstance():SingletonObject
   * Rather than using new SingletonObject to create a new
   * object of the class, you need to use
   * SingletonObject.getInstance() to point to the Singleton
   * class.
   */
  public function SingletonObject(e:SingletonEnforcer){
   trace("new singleton object created");
  }

  public static function getInstance():SingletonObject{
   if(_instance==null){
    _instance=new SingletonObject(new SingletonEnforcer);
   }
   return _instance;
  }
  
  /**
   * Here's our data for the DataGrid.
   */
  private var _expenses:ArrayCollection = new ArrayCollection([
   {selected:true, id:0, amount:2000},
   {selected:true, id:1, amount:1000},
   {selected:true, id:2, amount:100},
   {selected:true, id:3, amount:450},
   {selected:true, id:4, amount:100},
   {selected:true, id:5, amount:200}
  ]);
  
  [Bindable]
  public function get expenses():ArrayCollection
  {
   return _expenses;
  }
  
  public function set expenses(value:ArrayCollection):void
  {
   _expenses = value;
  }
  
  private var _selectedState:Number = 0;
  
  [Bindable]
  public function get selectedState():Number
  {
   return _selectedState;
  }

  public function set selectedState(value:Number):void
  {
   _selectedState = value;
  }
 }
}

/**
 * This class is needed in creating a singleton class.
 */
class SingletonEnforcer{
 
}

Renderers class for the header that comes with a custom checkbox with 3 different states - renderers/CustomHeaderCheckBoxRenderer.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:DefaultGridHeaderRenderer xmlns:fx="http://ns.adobe.com/mxml/2009" 
        xmlns:s="library://ns.adobe.com/flex/spark" 
        xmlns:mx="library://ns.adobe.com/flex/mx" 
        xmlns:component="renderers.component.*" 
        width="100%" click="clickHandler(event)">
 <fx:Declarations>
  <!-- Place non-visual elements (e.g., services, value objects) here -->
 </fx:Declarations>
 <fx:Script>
  <![CDATA[
   import object.SingletonObject;
   /**
    * We are using a singleton object to store the objects/data.
    */
   private var dataObj:SingletonObject = 
    SingletonObject.getInstance();
   
   protected function clickHandler(event:MouseEvent):void
   {
    event.stopImmediatePropagation();
   }
   
  ]]>
 </fx:Script>
 <s:states>
  <s:State name="normal" />
  <s:State name="hovered" />
  <s:State name="down" />
 </s:states>     
 
 <!-- layer 1: shadow -->
 <!--- @private -->
 <s:Rect id="shadow" left="-1" right="-1" top="-1" bottom="-1" radiusX="2">
  <s:fill>
   <s:LinearGradient rotation="90">
    <s:GradientEntry color="0x000000" 
         color.down="0xFFFFFF"
         alpha="0.01"
         alpha.down="0" />
    <s:GradientEntry color="0x000000" 
         color.down="0xFFFFFF" 
         alpha="0.07"
         alpha.down="0.5" />
   </s:LinearGradient>
  </s:fill>
 </s:Rect>
 
 <!-- layer 2: fill -->
 <!--- @private -->
 <s:Rect id="fill" left="0" right="0" top="0" bottom="0">
  <s:fill>
   <s:LinearGradient rotation="90">
    <s:GradientEntry color="0xFFFFFF" 
         color.hovered="0xBBBDBD" 
         color.down="0xAAAAAA" 
         alpha="0.85" />
    <s:GradientEntry color="0xD8D8D8" 
         color.hovered="0x9FA0A1" 
         color.down="0x929496" 
         alpha="0.85" />
   </s:LinearGradient>
  </s:fill>
 </s:Rect>
 
 <!-- layer 3: fill lowlight -->
 <!--- @private -->
 <s:Rect id="lowlight" left="0" right="0" top="0" bottom="0">
  <s:fill>
   <s:LinearGradient rotation="270">
    <s:GradientEntry color="0x000000" ratio="0.0" alpha="0.0627" />
    <s:GradientEntry color="0x000000" ratio="0.48" alpha="0.0099" />
    <s:GradientEntry color="0x000000" ratio="0.48001" alpha="0" />
   </s:LinearGradient>
  </s:fill>
 </s:Rect>
 
 <!-- layer 4: fill highlight -->
 <!--- @private -->
 <s:Rect id="highlight" left="0" right="0" top="0" bottom="0">
  <s:fill>
   <s:LinearGradient rotation="90">
    <s:GradientEntry color="0xFFFFFF"
         ratio="0.0"
         alpha="0.33" 
         alpha.hovered="0.22" 
         alpha.down="0.12"/>
    <s:GradientEntry color="0xFFFFFF"
         ratio="0.48"
         alpha="0.33"
         alpha.hovered="0.22"
         alpha.down="0.12" />
    <s:GradientEntry color="0xFFFFFF"
         ratio="0.48001"
         alpha="0" />
   </s:LinearGradient>
  </s:fill>
 </s:Rect>  
 
 <!-- layer 5: highlight stroke (all states except down) -->
 <!--- @private -->
 <s:Rect id="highlightStroke" left="0" right="0" top="0" bottom="0" excludeFrom="down">
  <s:stroke>
   <s:LinearGradientStroke rotation="90" weight="1">
    <s:GradientEntry color="0xFFFFFF" alpha.hovered="0.22" />
    <s:GradientEntry color="0xD8D8D8" alpha.hovered="0.22" />
   </s:LinearGradientStroke>
  </s:stroke>
 </s:Rect>
 
 <!-- layer 6: highlight stroke (down state only) -->
 <!--- @private -->
 <s:Rect id="hldownstroke1" left="0" right="0" top="0" bottom="0" includeIn="down">
  <s:stroke>
   <s:LinearGradientStroke rotation="90" weight="1">
    <s:GradientEntry color="0x000000" alpha="0.25" ratio="0.0" />
    <s:GradientEntry color="0x000000" alpha="0.25" ratio="0.001" />
    <s:GradientEntry color="0x000000" alpha="0.07" ratio="0.0011" />
    <s:GradientEntry color="0x000000" alpha="0.07" ratio="0.965" />
    <s:GradientEntry color="0x000000" alpha="0.00" ratio="0.9651" />
   </s:LinearGradientStroke>
  </s:stroke>
 </s:Rect>
 <!--- @private -->
 <s:Rect id="hldownstroke2" left="1" right="1" top="1" bottom="1" includeIn="down">
  <s:stroke>
   <s:LinearGradientStroke rotation="90" weight="1">
    <s:GradientEntry color="0x000000" alpha="0.09" ratio="0.0" />
    <s:GradientEntry color="0x000000" alpha="0.00" ratio="0.0001" />
   </s:LinearGradientStroke>
  </s:stroke>
 </s:Rect>
 <s:VGroup verticalAlign="middle" 
     horizontalAlign="center" 
     width="100%"
     height="100%">
  <component:CustomCheckBox styleName="customCheckBox"
          selectedValue="{dataObj.selectedState}"/>
 </s:VGroup>
</s:DefaultGridHeaderRenderer>


Custom checkbox that supports 3 different states - renderers/component/CustomCheckBox.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:CheckBox xmlns:fx="http://ns.adobe.com/mxml/2009" 
   xmlns:s="library://ns.adobe.com/flex/spark" 
   xmlns:mx="library://ns.adobe.com/flex/mx" 
   click="clickHandler(event)" 
   mouseOver="mouseOverHandler(event)" 
   mouseDown="mouseDownHandler(event)" 
   mouseOut="mouseOutHandler(event)">
 <!-- Declaring all the different types of state in this component -->
 <fx:Metadata>
  [SkinState("up")]
  [SkinState("over")]
  [SkinState("down")]
  [SkinState("disabled")]
  [SkinState("upAndSelected")]
  [SkinState("overAndSelected")]
  [SkinState("downAndSelected")]
  [SkinState("disabledAndSelected")]
  [SkinState("upAndSemiSelected")]
  [SkinState("overAndSemiSelected")]
  [SkinState("downAndSemiSelected")]
  [SkinState("disabledAndSemiSelected")]
 </fx:Metadata>
 <fx:Script>
  <![CDATA[
   import events.CustomCheckBoxEvents;
   /**
    * Rather than select and unselected state,
    * we need 3 different states now.
    * 
    * 0 - not selected
    * 1 - semi selected
    * 2 - selected
    * 
    * @default 0
    */
   private var _selectedValue:Number = 0;

   public function get selectedValue():Number
   {
    return _selectedValue;
   }

   public function set selectedValue(value:Number):void
   {
    _selectedValue = value;
    updateState();
   }
   
   /**
    * For storing the component state
    * 
    * 0 - up
    * 1 - over
    * 2 - down
    * 
    * @default 0
    */
   private var currentComponentState:Number = 0;
   
   /**
    * For the skin file to find out the state that it
    * should be displaying.
    */
   override protected function getCurrentSkinState():String
   {
    return this.currentState;
   }
   
   /**
    * Upon clicking on this component, we need to raise
    * a few events.
    */
   override protected function clickHandler(event:MouseEvent):void
   {
    event.stopImmediatePropagation();
    switch (_selectedValue)
    {
     //when unselected
     case 0:
      _selectedValue = 2;
      this.dispatchEvent(
       new CustomCheckBoxEvents(
        CustomCheckBoxEvents.SELECT_ALL_ITEMS));
      break;
     //when semi selected
     case 1:
      _selectedValue = 2;
      this.dispatchEvent(
       new CustomCheckBoxEvents(
        CustomCheckBoxEvents.SELECT_ALL_ITEMS));
      break;
     //when selected
     case 2:
      _selectedValue = 0;
      this.dispatchEvent(
       new CustomCheckBoxEvents(
        CustomCheckBoxEvents.UNSELECT_ALL_ITEMS));
      break;
    }
    updateState();
   }
   
   /**
    * Upon mouse over on this component, we need to update
    * the state.
    */
   protected function mouseOverHandler(event:MouseEvent):void
   {
    event.stopImmediatePropagation();
    currentComponentState = 1;
    updateState();
   }
   
   /**
    * Upon mouse down on this component, we need to update
    * the state.
    */
   protected function mouseDownHandler(event:MouseEvent):void
   {
    event.stopImmediatePropagation();
    currentComponentState = 2;
    updateState();
   }
   
   /**
    * Upon mouse out on this component, we need to update
    * the state.
    */
   protected function mouseOutHandler(event:MouseEvent):void
   {
    event.stopImmediatePropagation();
    currentComponentState = 0;
    updateState();
   }
   
   private function updateState():void
   {
    var tempStr:String = "";
    switch(_selectedValue)
    {
     //when unselected
     case 0:
      tempStr = "";
      break;
     //when semi selected
     case 1:
      tempStr = "AndSemiSelected";
      break;
     //when selected
     case 2:
      tempStr = "AndSelected";
      break;
    }
    if(this.enabled)
    {
     switch(currentComponentState)
     {
      //when mouse out
      case 0:
       tempStr = "up" + tempStr;
       break;
      //when mouse over
      case 1:
       tempStr = "over" + tempStr;
       break;
      //when mouse down
      case 2:
       tempStr = "down" + tempStr;
       break;
     }
    }else{
     tempStr = "disabled" + tempStr;
    }
    this.currentState = tempStr;
   }
  ]]>
 </fx:Script>
 <!-- 
  Upon swaping to these states, we need to call the function
  invalidateSkinState() to update the skin immediately.
 -->
 <s:states>
  <s:State name="up" enterState="invalidateSkinState()"/>
  <s:State name="over" enterState="invalidateSkinState()"/>
  <s:State name="down" enterState="invalidateSkinState()"/>
  <s:State name="disabled" enterState="invalidateSkinState()"/>
  <s:State name="upAndSelected" enterState="invalidateSkinState()"/>
  <s:State name="overAndSelected" enterState="invalidateSkinState()"/>
  <s:State name="downAndSelected" enterState="invalidateSkinState()"/>
  <s:State name="disabledAndSelected" enterState="invalidateSkinState()"/>
  <s:State name="upAndSemiSelected" enterState="invalidateSkinState()"/>
  <s:State name="overAndSemiSelected" enterState="invalidateSkinState()"/>
  <s:State name="downAndSemiSelected" enterState="invalidateSkinState()"/>
  <s:State name="disabledAndSemiSelected" enterState="invalidateSkinState()"/>
 </s:states>
</s:CheckBox>

Skin class for the custom checkbox - skins/CustomCheckBoxSkin.mxml
<?xml version="1.0" encoding="utf-8"?>

<!--

    ADOBE SYSTEMS INCORPORATED
    Copyright 2008 Adobe Systems Incorporated
    All Rights Reserved.

    NOTICE: Adobe permits you to use, modify, and distribute this file
    in accordance with the terms of the license agreement accompanying it.

-->

<!--- The default skin class for the Spark CheckBox component.  

      @see spark.components.CheckBox
        
      @langversion 3.0
      @playerversion Flash 10
      @playerversion AIR 1.5
      @productversion Flex 4
-->
<s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009"
    xmlns:s="library://ns.adobe.com/flex/spark"
    xmlns:fb="http://ns.adobe.com/flashbuilder/2009"
    alpha.disabledStates="0.5">
 <fx:Metadata>[HostComponent("renderers.component.CustomCheckBox")]</fx:Metadata>

    <fx:Script fb:purpose="styling">
        /* Define the skin elements that should not be colorized. 
           For button, the graphics are colorized but the label is not. */
        static private const exclusions:Array = ["labelDisplay", "check"];

       /** 
        * @private 
        */     
        override public function get colorizeExclusions():Array {return exclusions;}
        
        /* Define the symbol fill items that should be colored by the "symbolColor" style. */
        static private const symbols:Array = ["checkMarkFill", "semiCheckMarkFill"];

       /**
        * @private 
        */
        override public function get symbolItems():Array {return symbols};
        
        /**
         * @private
         */
        override protected function initializationComplete():void
        {
            useChromeColor = true;
            super.initializationComplete();
        }
    </fx:Script>
    
    <fx:Script>
        <![CDATA[
            /** 
             * @private 
             */     
            private static const focusExclusions:Array = ["labelDisplay"];

            /**
             * @private
             */
            override public function get focusSkinExclusions():Array { return focusExclusions;};
        ]]>
    </fx:Script>
    
 <!--
  All the states of this component.
 -->
    <s:states>
        <s:State name="up" />
        <s:State name="over" stateGroups="overStates" />
        <s:State name="down" stateGroups="downStates" />
        <s:State name="disabled" stateGroups="disabledStates" />
        <s:State name="upAndSelected" stateGroups="selectedStates" />
        <s:State name="overAndSelected" stateGroups="overStates, selectedStates" />
        <s:State name="downAndSelected" stateGroups="downStates, selectedStates" />
        <s:State name="disabledAndSelected" stateGroups="disabledStates, selectedStates" />
  <s:State name="upAndSemiSelected" stateGroups="semiSelectedStates" />
  <s:State name="overAndSemiSelected" stateGroups="overStates, semiSelectedStates" />
  <s:State name="downAndSemiSelected" stateGroups="downStates, semiSelectedStates" />
  <s:State name="disabledAndSemiSelected" stateGroups="disabledStates, semiSelectedStates" />  
    </s:states>
    
    <s:Group verticalCenter="0" width="13" height="13" layoutDirection="ltr">
        <!-- drop shadow -->
        <s:Rect left="-1" top="-1" right="-1" bottom="-1">
            <s:stroke>
                <s:LinearGradientStroke rotation="90" weight="1">
                    <s:GradientEntry color="0x000000" 
                                   color.downStates="0xFFFFFF"
                                   alpha="0.011"
                                   alpha.downStates="0" />
                    <s:GradientEntry color="0x000000" 
                                   color.downStates="0xFFFFFF" 
                                   alpha="0.121"
                                   alpha.downStates="0.57" />
                </s:LinearGradientStroke>
            </s:stroke>
        </s:Rect>
        
        <!-- fill -->
        <s:Rect left="1" top="1" right="1" bottom="1">
            <s:fill>
                <s:LinearGradient rotation="90">
                    <s:GradientEntry color="0xFFFFFF" 
                                   color.overStates="0xBBBDBD" 
                                   color.downStates="0xAAAAAA" 
                                   alpha="0.85" />
                    <s:GradientEntry color="0xD8D8D8" 
                                   color.overStates="0x9FA0A1" 
                                   color.downStates="0x929496" 
                                   alpha="0.85" />
                </s:LinearGradient>
            </s:fill>
        </s:Rect>
        
        <!-- fill highlight -->
        <s:Rect left="1" right="1" top="1" height="5">
            <s:fill>
                <s:SolidColor color="0xFFFFFF" alpha="0.33" alpha.downStates="0" />
            </s:fill>
        </s:Rect>
        
        <!-- layer 6: highlight stroke (all states except down) -->
        <s:Rect left="1" right="1" top="1" bottom="1" excludeFrom="downStates">
            <s:stroke>
                <s:LinearGradientStroke rotation="90" weight="1">
                    <s:GradientEntry color="0xFFFFFF" alpha.overStates="0.33" />
                    <s:GradientEntry color="0xFFFFFF" alpha="0.12" alpha.overStates="0.0396" />
                </s:LinearGradientStroke>
            </s:stroke>
        </s:Rect>
        
        <!-- layer 6: highlight stroke (down state only) -->
        <s:Rect left="1" top="1" bottom="1" width="1" includeIn="downStates">
            <s:fill>
                <s:SolidColor color="0x000000" alpha="0.07" />
            </s:fill>
        </s:Rect>
        <s:Rect right="1" top="1" bottom="1" width="1" includeIn="downStates">
            <s:fill>
                <s:SolidColor color="0x000000" alpha="0.07" />
            </s:fill>
        </s:Rect>
        <s:Rect left="1" top="1" right="1" height="1" includeIn="downStates">
            <s:fill>
                <s:SolidColor color="0x000000" alpha="0.25" />
            </s:fill>
        </s:Rect>
        <s:Rect left="1" top="2" right="1" height="1" includeIn="downStates">
            <s:fill>
                <s:SolidColor color="0x000000" alpha="0.09" />
            </s:fill>
        </s:Rect>
        
        <!-- border - put on top of the fill so it doesn't disappear when scale is less than 1 -->
        <s:Rect left="0" top="0" right="0" bottom="0">
            <s:stroke>
                <s:LinearGradientStroke rotation="90" weight="1">
                    <s:GradientEntry color="0x000000" 
                                   alpha="0.5625"
                                   alpha.downStates="0.6375" />
                    <s:GradientEntry color="0x000000" 
                                   alpha="0.75"
                                   alpha.downStates="0.85" />
                </s:LinearGradientStroke>
            </s:stroke>
        </s:Rect>
    
        <!-- checkmark -->
        <!--- The checkmark in the box for this skin. To create a custom check mark, create a custom skin class. -->
        <s:Path left="2" top="0" includeIn="selectedStates" id="check" itemCreationPolicy="immediate"
                data="M 9.2 0.1 L 4.05 6.55 L 3.15 5.0 L 0.05 5.0 L 4.6 9.7 L 12.05 0.1 L 9.2 0.1">        
            <s:fill>
                <!--- 
                    @private 
                    The solid color fill for the CheckBox's checkmark. The default alpha is .9, and the default fill color is 0x000000. 
                -->
                <s:SolidColor id="checkMarkFill" color="0" alpha="0.8" />
            </s:fill>
        </s:Path>
  
  <!-- semi selected checkmark -->
  <!--- The checkmark in the box for this skin. To create a custom check mark, create a custom skin class. -->
  <s:Path left="2" top="2" includeIn="semiSelectedStates" id="semiCheck" itemCreationPolicy="immediate"
    data="M 1 1 L 10 1 L 10 10 L 1 10 L 1 1">        
   <s:fill>
    <!--- 
    @private 
    The solid color fill for the CheckBox's checkmark. The default alpha is .9, and the default fill color is 0x000000. 
    -->
    <s:SolidColor id="semiCheckMarkFill" color="0" alpha="0.8" />
   </s:fill>
  </s:Path>
    </s:Group>

    <!-- Label -->
    <!--- @copy spark.components.supportClasses.ButtonBase#labelDisplay -->
    <s:Label id="labelDisplay"
             textAlign="start"
             verticalAlign="middle"
             maxDisplayedLines="1"
             left="18" right="0" top="3" bottom="3" 
    verticalCenter="2" visible="false"/>
</s:SparkSkin>

Renderers class for the individual items that comes with a normal checkbox - CustomCheckBoxRenderer.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:GridItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009" 
     xmlns:s="library://ns.adobe.com/flex/spark" 
     xmlns:mx="library://ns.adobe.com/flex/mx" 
     implements="spark.components.gridClasses.IGridItemRenderer"
     width="100%">
 
 <fx:Script>
  <![CDATA[
   import events.CustomCheckBoxEvents;
   /** 
    * Upon setting the data into the renderer, we need to
    * change the state of the checkbox.
    */
   override public function set data(value:Object):void
   {
    super.data = value;
    chk.selected = data[this.column.dataField]
   } 
   
   /**
    * Upon cliking on the check box, we need to dispatch
    * some events.
    */   
   protected function chk_clickHandler(event:MouseEvent):void
   {
    event.stopImmediatePropagation();
    if(chk.selected)
    {
     this.dispatchEvent(
      new CustomCheckBoxEvents(
       CustomCheckBoxEvents.SELECT_AN_ITEM,
      this.data));
    }else{
     
     this.dispatchEvent(
      new CustomCheckBoxEvents(
       CustomCheckBoxEvents.UNSELECT_AN_ITEM,
      this.data));
    }
   }
   
  ]]>
 </fx:Script>
 <s:VGroup verticalAlign="middle" 
     horizontalAlign="center"
     width="100%" 
     height="100%">
  <s:CheckBox id="chk"
     click="chk_clickHandler(event)"/>
 </s:VGroup>
</s:GridItemRenderer>

CSS file for the application - ../css/style.css
/* CSS file */
@namespace s "library://ns.adobe.com/flex/spark";
@namespace mx "library://ns.adobe.com/flex/mx";

.customCheckBox{
 skinClass: ClassReference("skins.CustomCheckBoxSkin");
}
* Click here for the demo shown in this post.
  (Try changing some of the checkbox to reflect the change of state in the topmost
  checkbox.)
^ Click here for the source files for the demo.