Sunday, September 16, 2012

Flash: Playing with Tabbing Sequence

You have created a simple form and rather than left to right, you wanted to change the tab sequence a bit, but how to do that?

Source code of the main application file - SimpleTabSequence.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;
   
   /*
    When the laste checkbox has been selected, we
    will change the tab sequence from top to bottom,
    else it will be bottom to top. 
   */
   protected function rdoChangeHandler(event:Event):void
   {
    if(chk1.selected)
    {
     setupSeq();
    }else{
     setupSeq(false);
    }
   }
   
   // Upon CreationComplete, setup the tab sequence from 
   // top to bottom.
   protected function creationCompleteEvent(e:FlexEvent):void
   {
    setupSeq();
   }
   
   /*
    Most of the work will be done here. It will assign 
    the tabIndex of all the components and it will also
    remove one of the checkbox from the tab sequence
    upon selection.
   */
   private function setupSeq(isTopdown:Boolean = true):void
   {
    if(isTopdown)
    {
     txtTxt0.tabIndex = 1;
     txtTxt1.tabIndex = 2;
     btn0.tabIndex = 3;
     txtTxt2.tabIndex = 4;
     btn1.tabIndex = 5;
     if(!chk0.selected)
     {
      chk0.tabIndex = 6;
      chk1.tabIndex = 7;
     }else{
      chk1.tabIndex = 6;
     }
    }else{
     if(!chk0.selected)
     {
      txtTxt0.tabIndex = 7;
      txtTxt1.tabIndex = 6;
      btn0.tabIndex = 5;
      txtTxt2.tabIndex = 4;
      btn1.tabIndex = 3;
      chk0.tabIndex = 2;
     }else{
      txtTxt0.tabIndex = 6;
      txtTxt1.tabIndex = 5;
      btn0.tabIndex = 4;
      txtTxt2.tabIndex = 3;
      btn1.tabIndex = 2;
     }
     chk1.tabIndex = 1;
    }
    chk0.tabFocusEnabled = !chk0.selected;
    lblTxt0.text = "Textfield(" + txtTxt0.tabIndex + ")";
    lblTxt1.text = "Textfield(" + txtTxt1.tabIndex + ")";
    btn0.label = "Does Nothing(" + btn0.tabIndex + ")";
    lblTxt2.text = "Textfield(" + txtTxt2.tabIndex + ")";
    btn1.label = "Not going to do anything(" + 
     btn1.tabIndex + ")";
    if(!chk0.selected)
    {
     chk0.label = "Checking will remove this " +
      "from tabbing(" + chk0.tabIndex + ")";
    }else{
     chk0.label = "Checking will remove this " +
      "from tabbing";
    }
    chk1.label = "Tabbing Sequence Is Top To " +
     "Bottom(" + chk1.tabIndex + ")";
   }
   
  ]]>
 </fx:Script>
 <!-- Just a list of components -->
 <s:VGroup width="100%" height="100%"
     verticalAlign="middle" horizontalAlign="center">
  <s:VGroup width="300" height="100%"
      verticalAlign="middle" horizontalAlign="center">
   <s:HGroup width="100%"
       horizontalAlign="center"
       verticalAlign="middle">
    <s:Label id="lblTxt0"/>
    <s:TextInput id="txtTxt0"/>
    <s:Spacer width="100%"/>
    <s:Label id="lblTxt1"
       text=""/>
    <s:TextInput id="txtTxt1"/>
   </s:HGroup>
   <s:HGroup width="100%" 
       horizontalAlign="center">
    <s:Button id="btn0" />
   </s:HGroup>
   <s:HGroup width="100%"
       horizontalAlign="center"
       verticalAlign="middle">
    <s:Label id="lblTxt2"/>
    <s:TextInput id="txtTxt2"/>
   </s:HGroup>
   <s:HGroup width="100%"
       horizontalAlign="center">
    <s:Button id="btn1"/>
   </s:HGroup>
   <s:HGroup width="100%"
       horizontalAlign="center">
    <s:CheckBox id="chk0" 
       change="rdoChangeHandler(event)" />
   </s:HGroup>
   <s:HGroup width="100%"
       horizontalAlign="center">
    <s:CheckBox id="chk1"  
       selected="true"
       change="rdoChangeHandler(event)" />
   </s:HGroup>
  </s:VGroup>
 </s:VGroup>
</s:Application>
* Click here for the demo shown in this post.
^ Click here for the source files for the demo.

Friday, September 7, 2012

AS3: In Search of the missing ReleaseOutside

In the older flash, or during the AS2 era, there's a onReleaseOutside that allows you to click on a button and release it outside. However, in AS3, one could easily find MouseEvents like MOUSE_DOWN, MOUSE_UP, CLICK, etc... but there isn't a RELEASE_OUTSIDE action, so how do work around it?

Time for some source files - SimpleMouseReleaseOutside.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;
   
   //Upon creation complete, setup the button event of the button
   //and setup the check box
   protected function creationCompleteEvent(event:FlexEvent):void
   {
    btn1.buttonMode = true;
    btn1.label = "Select Me Please";
    btn1.addEventListener(MouseEvent.MOUSE_DOWN, btnMouseDownEvent);
    
    chk1.buttonMode = true;
    chk1.label = "Click me to enable 'ReleaseOutside' on the btn.";
    chk1.selected = false;
   }
   
   //Upon performing a MOUSE DOWN action on the button, add the 
   //listeners for MOUSE UP and if the checkbox is selected, we
   //will be adding a MOUSE UP listener for the stage (This
   //will perform like a ReleaseOutside event in as2.
   private function btnMouseDownEvent(event:Event):void
   {
    btn1.label = "I'm selected";
    btn1.addEventListener(
     MouseEvent.MOUSE_UP, btnMouseUpEvent);
    if(chk1.selected)
    {
     stage.addEventListener(
      MouseEvent.MOUSE_UP, btnMouseUpEvent);
    }
   }
   
   //Upon performing a MOUSE UP action on the button or anywhere
   //in the file, we will be removing the listeners for the button
   //away.
   private function btnMouseUpEvent(event:Event):void
   {
    btn1.label = "Select Me Please";
    btn1.removeEventListener(
     MouseEvent.MOUSE_UP, btnMouseUpEvent);
    if(chk1.selected)
    {
     stage.removeEventListener(
      MouseEvent.MOUSE_UP, btnMouseUpEvent);
    }
   }
   
  ]]>
 </fx:Script>
 <s:VGroup width="100%"
     height="100%"
     horizontalAlign="center">
  <s:Spacer height="100%"/>
  <s:Button id="btn1" 
      width="200"/>
  <s:Spacer height="100%"/>
  <s:CheckBox id="chk1"/>
  <s:Spacer height="100%"/>
 </s:VGroup>
</s:Application>
* Click here for the demo shown in this post.
^ Click here for the source files for the demo.

Saturday, September 1, 2012

Flex: Locating a point

Probably there' a requirement that requires you to place an icon for both the highest and lowest y value of a chart, but how do you do it?

And here's my answer to the above question. :P Time for some coding... Here's my main application file - "SimpleChartPositionOfAPoint.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"
      backgroundColor="#CDCDCD"
      creationComplete="creationCompleteEvent(event)">
 <fx:Script>
  <![CDATA[
   import flashx.textLayout.conversion.TextConverter;
   
   import mx.charts.HitData;
   import mx.charts.chartClasses.IChartElement2;
   import mx.charts.series.LineSeries;
   import mx.collections.ArrayCollection;
   import mx.collections.Sort;
   import mx.collections.SortField;
   import mx.events.FlexEvent;
   import mx.formatters.DateFormatter;
   
   import spark.events.IndexChangeEvent;
   
   //Records used in the chart
   [Bindable]
   private var myData:XML = 
    <records>
     <record>
      <date>16/11/2012</date>
      <people>74</people>
     </record>
     <record>
      <date>24/07/2013</date>
      <people>99</people>
     </record>
     <record>
      <date>05/04/2013</date>
      <people>79</people>
     </record>
     <record>
      <date>08/07/2012</date>
      <people>54</people>
     </record>
     <record>
      <date>22/11/2012</date>
      <people>42</people>
     </record>
     <record>
      <date>10/04/2012</date>
      <people>42</people>
     </record>
     <record>
      <date>17/03/2012</date>
      <people>57</people>
     </record>
     <record>
      <date>16/10/2011</date>
      <people>63</people>
     </record>
     <record>
      <date>06/02/2012</date>
      <people>80</people>
     </record>
     <record>
      <date>09/01/2012</date>
      <people>2</people>
     </record>
     <record>
      <date>18/11/2011</date>
      <people>100</people>
     </record>
     <record>
      <date>25/11/2011</date>
      <people>88</people>
     </record>
     <record>
      <date>29/05/2012</date>
      <people>94</people>
     </record>
     <record>
      <date>30/03/2013</date>
      <people>99</people>
     </record>
     <record>
      <date>08/09/2012</date>
      <people>33</people>
     </record>
     <record>
      <date>26/01/2012</date>
      <people>33</people>
     </record>
     <record>
      <date>12/11/2012</date>
      <people>48</people>
     </record>
     <record>
      <date>17/05/2013</date>
      <people>57</people>
     </record>
     <record>
      <date>13/04/2012</date>
      <people>57</people>
     </record>
     <record>
      <date>18/07/2013</date>
      <people>81</people>
     </record>
     <record>
      <date>09/08/2012</date>
      <people>60</people>
     </record>
     <record>
      <date>04/09/2012</date>
      <people>49</people>
     </record>
     <record>
      <date>29/12/2012</date>
      <people>15</people>
     </record>
     <record>
      <date>17/08/2011</date>
      <people>1</people>
     </record>
     <record>
      <date>09/10/2012</date>
      <people>76</people>
     </record>
     <record>
      <date>20/02/2012</date>
      <people>62</people>
     </record>
     <record>
      <date>24/06/2013</date>
      <people>70</people>
     </record>
     <record>
      <date>17/07/2013</date>
      <people>17</people>
     </record>
     <record>
      <date>21/04/2012</date>
      <people>32</people>
     </record>
     <record>
      <date>11/04/2013</date>
      <people>92</people>
     </record>
     <record>
      <date>02/08/2013</date>
      <people>97</people>
     </record>
     <record>
      <date>27/12/2011</date>
      <people>5</people>
     </record>
     <record>
      <date>01/05/2012</date>
      <people>90</people>
     </record>
     <record>
      <date>20/04/2013</date>
      <people>75</people>
     </record>
     <record>
      <date>26/10/2012</date>
      <people>60</people>
     </record>
     <record>
      <date>02/01/2012</date>
      <people>31</people>
     </record>
     <record>
      <date>04/02/2013</date>
      <people>17</people>
     </record>
     <record>
      <date>17/04/2013</date>
      <people>16</people>
     </record>
     <record>
      <date>22/03/2013</date>
      <people>94</people>
     </record>
     <record>
      <date>10/09/2011</date>
      <people>97</people>
     </record>
     <record>
      <date>27/11/2012</date>
      <people>18</people>
     </record>
     <record>
      <date>15/03/2013</date>
      <people>94</people>
     </record>
     <record>
      <date>17/10/2011</date>
      <people>85</people>
     </record>
     <record>
      <date>18/03/2012</date>
      <people>12</people>
     </record>
     <record>
      <date>09/10/2011</date>
      <people>92</people>
     </record>
     <record>
      <date>08/09/2012</date>
      <people>17</people>
     </record>
     <record>
      <date>22/10/2012</date>
      <people>45</people>
     </record>
     <record>
      <date>09/11/2012</date>
      <people>40</people>
     </record>
     <record>
      <date>06/09/2012</date>
      <people>75</people>
     </record>
     <record>
      <date>13/08/2012</date>
      <people>2</people>
     </record>
     <record>
      <date>04/03/2012</date>
      <people>20</people>
     </record>
     <record>
      <date>17/11/2012</date>
      <people>34</people>
     </record>
     <record>
      <date>01/02/2012</date>
      <people>51</people>
     </record>
     <record>
      <date>29/08/2011</date>
      <people>35</people>
     </record>
     <record>
      <date>11/02/2012</date>
      <people>35</people>
     </record>
     <record>
      <date>02/06/2012</date>
      <people>26</people>
     </record>
     <record>
      <date>20/01/2013</date>
      <people>98</people>
     </record>
     <record>
      <date>07/02/2013</date>
      <people>4</people>
     </record>
     <record>
      <date>27/08/2012</date>
      <people>44</people>
     </record>
     <record>
      <date>12/12/2012</date>
      <people>29</people>
     </record>
     <record>
      <date>18/03/2012</date>
      <people>96</people>
     </record>
     <record>
      <date>01/09/2012</date>
      <people>40</people>
     </record>
     <record>
      <date>09/02/2013</date>
      <people>34</people>
     </record>
     <record>
      <date>22/09/2012</date>
      <people>86</people>
     </record>
     <record>
      <date>28/02/2012</date>
      <people>14</people>
     </record>
     <record>
      <date>02/02/2012</date>
      <people>94</people>
     </record>
     <record>
      <date>08/06/2013</date>
      <people>16</people>
     </record>
     <record>
      <date>23/03/2012</date>
      <people>32</people>
     </record>
     <record>
      <date>21/03/2013</date>
      <people>10</people>
     </record>
     <record>
      <date>07/04/2013</date>
      <people>10</people>
     </record>
     <record>
      <date>11/03/2013</date>
      <people>28</people>
     </record>
     <record>
      <date>02/11/2012</date>
      <people>28</people>
     </record>
     <record>
      <date>14/11/2011</date>
      <people>3</people>
     </record>
     <record>
      <date>05/02/2013</date>
      <people>12</people>
     </record>
     <record>
      <date>21/03/2013</date>
      <people>41</people>
     </record>
     <record>
      <date>30/09/2012</date>
      <people>96</people>
     </record>
     <record>
      <date>19/02/2013</date>
      <people>29</people>
     </record>
     <record>
      <date>09/07/2013</date>
      <people>86</people>
     </record>
     <record>
      <date>30/04/2013</date>
      <people>35</people>
     </record>
     <record>
      <date>21/01/2012</date>
      <people>4</people>
     </record>
     <record>
      <date>26/06/2013</date>
      <people>88</people>
     </record>
     <record>
      <date>17/04/2013</date>
      <people>55</people>
     </record>
     <record>
      <date>04/10/2011</date>
      <people>38</people>
     </record>
     <record>
      <date>20/03/2013</date>
      <people>38</people>
     </record>
     <record>
      <date>19/05/2013</date>
      <people>91</people>
     </record>
     <record>
      <date>28/08/2011</date>
      <people>73</people>
     </record>
     <record>
      <date>31/08/2011</date>
      <people>65</people>
     </record>
     <record>
      <date>11/03/2013</date>
      <people>88</people>
     </record>
     <record>
      <date>10/06/2013</date>
      <people>78</people>
     </record>
     <record>
      <date>03/07/2013</date>
      <people>8</people>
     </record>
     <record>
      <date>08/10/2012</date>
      <people>16</people>
     </record>
     <record>
      <date>19/03/2012</date>
      <people>74</people>
     </record>
     <record>
      <date>28/09/2012</date>
      <people>49</people>
     </record>
     <record>
      <date>29/07/2013</date>
      <people>51</people>
     </record>
     <record>
      <date>05/10/2012</date>
      <people>60</people>
     </record>
     <record>
      <date>18/02/2012</date>
      <people>63</people>
     </record>
     <record>
      <date>03/09/2011</date>
      <people>45</people>
     </record>
     <record>
      <date>30/12/2011</date>
      <people>76</people>
     </record>
     <record>
      <date>11/04/2013</date>
      <people>96</people>
     </record>
     <record>
      <date>15/06/2012</date>
      <people>55</people>
     </record>
    </records>;
   
   private var localSeries:LineSeries = new LineSeries();
   
   //This function will show a text box which is positioned
   //above the selected point
   protected function cb1ChangeEvent(event:IndexChangeEvent):void
   {
    //We will need the date, the date in numerical format
    //and the number of people during that date
    var tempDate:Date = event.currentTarget.selectedItem.date;
    var xPos:Number = tempDate.time;
    var yPos:Number = event.currentTarget.selectedItem.people;
    
    //Next, create a point withe the date in numerical format
    //and the number of people, which is used to create the
    //x and y axis of the chart
    var myPoint:Point = new Point(xPos,yPos);
    
    //Next, check it against the line series to find the 
    //and y postion of the point on the chart
    //Note: dataToLocal didn't calculate the gutters around
    //the chart, you need to calculate yrself.
    myPoint = localSeries.dataToLocal(xPos, yPos);
    
    //Next, offset the gutters on the left and top of the point
    myPoint.x += lineChart.getStyle("gutterLeft");
    myPoint.y += lineChart.getStyle("gutterTop");
    
    //find the global position of the point
    myPoint = lineChart.localToGlobal(myPoint);
    
    //followed by the step of mapping the point into the
    //layer abouve the chart 
    myPoint = canvas.globalToLocal(myPoint);
    
    //We will position the textfield above the selected point
    txtResult.visible = true;
    txtResult.x = myPoint.x - txtResult.width / 2;
    txtResult.y = myPoint.y - txtResult.height - 5;
    
    //Let's populate the textfield with some data.
    var tempStr:String = "";
    tempStr += "Date: " + dateFormatter(tempDate) + "<br>";
    tempStr += "No. of People: " + yPos;
    txtResult.textFlow = TextConverter.importToFlow(tempStr,
     TextConverter.TEXT_FIELD_HTML_FORMAT);
   }
   
   protected function creationCompleteEvent(event:FlexEvent):void
   {
    // Parsing the xml data into ArrayCollection
    var objArray:ArrayCollection = new ArrayCollection();
    var tempObj:Object;
    var dateArray:Array;
    var tempDate:Date;
    for(var i:int = 0; i < myData.record.length(); i ++)
    {
     tempObj = new Object();
     dateArray = String(myData.record[i].date).split("/");
     //Convert the date data into a Date Object
     tempDate = new Date(dateArray[2], 
      Number(dateArray[1]) - 1, 
      dateArray[0]);
     tempObj.date = tempDate;
     tempObj.time = tempDate.time;
     tempObj.people = myData.record[i].people;
     tempObj.label = dateFormatter(tempDate);
     objArray.addItem(tempObj);
    }
    
    //Create the SortField object for the "time" field 
    //in the ArrayCollection object, and make sure we
    //do a numeric sort.
    var dataSortField:SortField = new SortField();
    dataSortField.name = "time";
    dataSortField.numeric = true;
    
    //Create the Sort object and add the SortField 
    //object created earlier to the array of fields
    //to sort on.
    var numericDataSort:Sort = new Sort();
    numericDataSort.fields = [dataSortField];
    
    objArray.sort = numericDataSort;
    objArray.refresh();
    
    //Create the new series and set its properties.
    localSeries.dataProvider = objArray;
    localSeries.yField = "people";
    localSeries.xField = "date";
    
    //Back up the current series on the chart.
    var currentSeries:Array = lineChart.series;
    //Add the new series to the current Array of 
    //series.
    currentSeries.push(localSeries);
    //Add the new Array of series to the chart.
    lineChart.series = currentSeries;
    
    cb1.dataProvider = objArray;
   }
   
   //This function will return a string based on the
   //Date format DD/MM/YYYY.
   private function dateFormatter(tempDate:Date):String
   {
    var fmt:DateFormatter = new DateFormatter();
    fmt.formatString = "DD/MM/YYYY";
    return fmt.format(tempDate);
   }
   
   //We are customizing the datatip / tool tip of the
   //chart data.
   public function myDataTipFunction(e:HitData):String {
    var s:String = "";
    var tempDate:Date = e.item.date as Date;
    s += "Date: " + dateFormatter(tempDate) + "<br>";
    s += "No. of People: " + e.item.people;
    return s;
   }
   
  ]]>
 </fx:Script>
 <s:VGroup width="100%" 
     height="100%"
     verticalAlign="middle"
     horizontalAlign="center">
  <s:BorderContainer width="100%"
         height="100%"
         backgroundAlpha="0"
         borderVisible="false">
   <s:HGroup verticalAlign="middle" horizontalAlign="center"
       width="100%"
       height="100%">
    <!-- Need to set the gutterLeft and 
     gutterTop of the chart -->
    <mx:LineChart id="lineChart"
         gutterTop="0"
         gutterLeft="50"
         showDataTips="true" 
         width="80%"
         height="80%"
         dataTipFunction="myDataTipFunction">
     <mx:horizontalAxis>
      <mx:DateTimeAxis dataUnits="days" id="dateAxis" 
           alignLabelsToUnits="true"/> 
     </mx:horizontalAxis>
    </mx:LineChart>
   </s:HGroup>
   <s:BorderContainer width="100%" 
          height="100%"
          id="canvas"
          mouseEnabled="false"
          backgroundAlpha="0"
          borderVisible="false"
          mouseChildren="false">
    <s:TextArea width="150"
       height="50" 
        visible="false"
       id="txtResult"/>
   </s:BorderContainer>
  </s:BorderContainer>
  <s:HGroup width="100%" 
      verticalAlign="middle"
      horizontalAlign="center">
   <s:Label text="Select a Date:"/>
   <s:ComboBox id="cb1" 
       change="cb1ChangeEvent(event)"/>
  </s:HGroup>
 </s:VGroup>
</s:Application>
* Click here for the demo shown in this post.
^ Click here for the source files for the demo.

Friday, August 24, 2012

Flex: The not so global ToolTipManager...

I was playing around the ToolTipManager class today and I realised that the ToolTipManager class isn't so global after all. Although you can use ToolTipManager.enabled to show/hide all the tooltips but...

Here the source codes of my main application - NotReallyGlobalTooltip.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:Script>
  <![CDATA[
   import mx.charts.series.ColumnSeries;
   import mx.collections.ArrayCollection;
   import mx.events.FlexEvent;
   import mx.managers.ToolTipManager;
   
   
   //Records used in the chart
   [Bindable]
   private var myData:XML = 
    <records>
     <record>
      <month>Jan</month>
      <car>73</car>
     </record>
     <record>
      <month>Feb</month>
      <car>72</car>
     </record>
     <record>
      <month>Mar</month>
      <car>79</car>
     </record>
     <record>
      <month>Apr</month>
      <car>80</car>
     </record>
     <record>
      <month>May</month>
      <car>51</car>
     </record>
    </records>;
   
   protected function btnGlobalToolTipEvent(event:MouseEvent):void
   {
    //Toggle the visibility of the Tooltips for all the 
    //components except the charts 
    ToolTipManager.enabled = !ToolTipManager.enabled;
    updateBtns();
   }
   
   protected function btnChartToolTipEvent(event:MouseEvent):void
   {
    //Toggle the visibility of the Tooltips for all the 
    //items in the charts
    chartMain.showDataTips = !chartMain.showDataTips;
    updateBtns();
   }
   
   protected function btnSuperToolTipEvent(event:MouseEvent):void
   {
    //Toggle the visibility of the Tooltips for all the 
    //components and the charts and sync them
    if(ToolTipManager.enabled == chartMain.showDataTips)
    {
     ToolTipManager.enabled = !ToolTipManager.enabled;
     chartMain.showDataTips = !chartMain.showDataTips;
    }else{
     ToolTipManager.enabled = false;
     chartMain.showDataTips = false;
    }
    updateBtns();
   }
   
   protected function creationCompleteHandler(event:FlexEvent):void
   {
    updateBtns();
   }
   
   //This function will updates all the labels of the buttons.
   private function updateBtns():void
   {
    if(ToolTipManager.enabled == chartMain.showDataTips)
    {
     if(ToolTipManager.enabled)
     {
      btnSuperToolTip.label = 
       "All ToolTips Enabled";
     }else{
      btnSuperToolTip.label = 
       "All ToolTips Disabled";
     }
    }else{
     btnSuperToolTip.label = 
      "All ToolTips Mixed";
    }
    
    if(ToolTipManager.enabled)
    {
     btnGlobalToolTip.label = 
      "Global ToolTip Enabled";
    }else{
     btnGlobalToolTip.label = 
      "Global ToolTip Disabled";
    }
    
    if(chartMain.showDataTips)
    {
     btnChartToolTip.label = 
      "Chart ToolTip Enabled";
    }else{
     btnChartToolTip.label = 
      "Chart ToolTip Disabled"; 
    }
   }
  ]]>
 </fx:Script>
 <s:VGroup width="100%" height="100%" gap="10" 
     horizontalAlign="center" verticalAlign="middle">
  <mx:ColumnChart id="chartMain" dataProvider="{myData.record}">
   <mx:horizontalAxis>
    <mx:CategoryAxis 
     categoryField="month"/>
   </mx:horizontalAxis>
   <mx:verticalAxis>
    <mx:LinearAxis 
     minorInterval="10"
      maximum="100"/>
   </mx:verticalAxis>
   <mx:series>
    <mx:ColumnSeries 
     yField="car" 
     displayName="No Of Cars."/>
   </mx:series>  
  </mx:ColumnChart>
  <s:HGroup gap="10">
   <mx:Text text="Some Dummy Text with Tooltip" 
      toolTip="A empty tooltip"/>
   <s:Button label="Button"
       toolTip="that does nothing"/>
  </s:HGroup>
  <s:Spacer height="10"/>
  <mx:Text htmlText="Click on the buttons below and rollover
     <br>the components in the above to see the differences."
     textAlign="center"/>
  <s:HGroup gap="10">
   <s:Button id="btnGlobalToolTip"
       width="200" 
       click="btnGlobalToolTipEvent(event)"/>
   <s:Button id="btnChartToolTip"
       width="200" 
       click="btnChartToolTipEvent(event)"/>
   <s:Button id="btnSuperToolTip"
       width="200" 
       click="btnSuperToolTipEvent(event)"/>
  </s:HGroup>
 </s:VGroup>
</s:Application>
* Click here for the demo shown in this post.
^ Click here for the source files for the demo.

Wednesday, August 15, 2012

Generating Dummy Data for Testing

Sometimes it can be a quite troublesome coming up with a set of dummy data for testing out a set of programming codes. It can be even much more tiring where you wanted to test out a large quantity of data. I was googling around and I found...


'generatedata.com'
This sites seems to be pretty useful in generating dummy data.
You can also choose your desired Result Type (html, sql, xml, etc...)
and the type of Data Type that you are using (date, string,
auto incrementing number, postal codes, etc...). Lesser time needed
in entering or generating dummy data in the future. Woohoo~~~

* Click here to find out more about 'generatedata.com'.
^ Click here to generate your first set of dummy data now.

Sunday, August 12, 2012

Flex: Playing with the horizontal axis of a chart

I was playing with charts the other day and there was a requirement which requires me to find the minimum and the maximum points of the chart. Therefore, I have came up with this demo to help you is understanding charts better. :D

Source of the main application file - SimpleChartHorizontalAxis.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" 
    layout="absolute" 
    minWidth="800"
     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>
      <date>16/11/2012</date>
      <people>74</people>
     </record>
     <record>
      <date>24/07/2013</date>
      <people>99</people>
     </record>
     <record>
      <date>05/04/2013</date>
      <people>79</people>
     </record>
     <record>
      <date>08/07/2012</date>
      <people>54</people>
     </record>
     <record>
      <date>22/11/2012</date>
      <people>42</people>
     </record>
     <record>
      <date>10/04/2012</date>
      <people>42</people>
     </record>
     <record>
      <date>17/03/2012</date>
      <people>57</people>
     </record>
     <record>
      <date>16/10/2011</date>
      <people>63</people>
     </record>
     <record>
      <date>06/02/2012</date>
      <people>80</people>
     </record>
     <record>
      <date>09/01/2012</date>
      <people>2</people>
     </record>
     <record>
      <date>18/11/2011</date>
      <people>100</people>
     </record>
     <record>
      <date>25/11/2011</date>
      <people>88</people>
     </record>
     <record>
      <date>29/05/2012</date>
      <people>94</people>
     </record>
     <record>
      <date>30/03/2013</date>
      <people>99</people>
     </record>
     <record>
      <date>08/09/2012</date>
      <people>33</people>
     </record>
     <record>
      <date>26/01/2012</date>
      <people>33</people>
     </record>
     <record>
      <date>12/11/2012</date>
      <people>48</people>
     </record>
     <record>
      <date>17/05/2013</date>
      <people>57</people>
     </record>
     <record>
      <date>13/04/2012</date>
      <people>57</people>
     </record>
     <record>
      <date>18/07/2013</date>
      <people>81</people>
     </record>
     <record>
      <date>09/08/2012</date>
      <people>60</people>
     </record>
     <record>
      <date>04/09/2012</date>
      <people>49</people>
     </record>
     <record>
      <date>29/12/2012</date>
      <people>15</people>
     </record>
     <record>
      <date>17/08/2011</date>
      <people>1</people>
     </record>
     <record>
      <date>09/10/2012</date>
      <people>76</people>
     </record>
     <record>
      <date>20/02/2012</date>
      <people>62</people>
     </record>
     <record>
      <date>24/06/2013</date>
      <people>70</people>
     </record>
     <record>
      <date>17/07/2013</date>
      <people>17</people>
     </record>
     <record>
      <date>21/04/2012</date>
      <people>32</people>
     </record>
     <record>
      <date>11/04/2013</date>
      <people>92</people>
     </record>
     <record>
      <date>02/08/2013</date>
      <people>97</people>
     </record>
     <record>
      <date>27/12/2011</date>
      <people>5</people>
     </record>
     <record>
      <date>01/05/2012</date>
      <people>90</people>
     </record>
     <record>
      <date>20/04/2013</date>
      <people>75</people>
     </record>
     <record>
      <date>26/10/2012</date>
      <people>60</people>
     </record>
     <record>
      <date>02/01/2012</date>
      <people>31</people>
     </record>
     <record>
      <date>04/02/2013</date>
      <people>17</people>
     </record>
     <record>
      <date>17/04/2013</date>
      <people>16</people>
     </record>
     <record>
      <date>22/03/2013</date>
      <people>94</people>
     </record>
     <record>
      <date>10/09/2011</date>
      <people>97</people>
     </record>
     <record>
      <date>27/11/2012</date>
      <people>18</people>
     </record>
     <record>
      <date>15/03/2013</date>
      <people>94</people>
     </record>
     <record>
      <date>17/10/2011</date>
      <people>85</people>
     </record>
     <record>
      <date>18/03/2012</date>
      <people>12</people>
     </record>
     <record>
      <date>09/10/2011</date>
      <people>92</people>
     </record>
     <record>
      <date>08/09/2012</date>
      <people>17</people>
     </record>
     <record>
      <date>22/10/2012</date>
      <people>45</people>
     </record>
     <record>
      <date>09/11/2012</date>
      <people>40</people>
     </record>
     <record>
      <date>06/09/2012</date>
      <people>75</people>
     </record>
     <record>
      <date>13/08/2012</date>
      <people>2</people>
     </record>
     <record>
      <date>04/03/2012</date>
      <people>20</people>
     </record>
     <record>
      <date>17/11/2012</date>
      <people>34</people>
     </record>
     <record>
      <date>01/02/2012</date>
      <people>51</people>
     </record>
     <record>
      <date>29/08/2011</date>
      <people>35</people>
     </record>
     <record>
      <date>11/02/2012</date>
      <people>35</people>
     </record>
     <record>
      <date>02/06/2012</date>
      <people>26</people>
     </record>
     <record>
      <date>20/01/2013</date>
      <people>98</people>
     </record>
     <record>
      <date>07/02/2013</date>
      <people>4</people>
     </record>
     <record>
      <date>27/08/2012</date>
      <people>44</people>
     </record>
     <record>
      <date>12/12/2012</date>
      <people>29</people>
     </record>
     <record>
      <date>18/03/2012</date>
      <people>96</people>
     </record>
     <record>
      <date>01/09/2012</date>
      <people>40</people>
     </record>
     <record>
      <date>09/02/2013</date>
      <people>34</people>
     </record>
     <record>
      <date>22/09/2012</date>
      <people>86</people>
     </record>
     <record>
      <date>28/02/2012</date>
      <people>14</people>
     </record>
     <record>
      <date>02/02/2012</date>
      <people>94</people>
     </record>
     <record>
      <date>08/06/2013</date>
      <people>16</people>
     </record>
     <record>
      <date>23/03/2012</date>
      <people>32</people>
     </record>
     <record>
      <date>21/03/2013</date>
      <people>10</people>
     </record>
     <record>
      <date>07/04/2013</date>
      <people>10</people>
     </record>
     <record>
      <date>11/03/2013</date>
      <people>28</people>
     </record>
     <record>
      <date>02/11/2012</date>
      <people>28</people>
     </record>
     <record>
      <date>14/11/2011</date>
      <people>3</people>
     </record>
     <record>
      <date>05/02/2013</date>
      <people>12</people>
     </record>
     <record>
      <date>21/03/2013</date>
      <people>41</people>
     </record>
     <record>
      <date>30/09/2012</date>
      <people>96</people>
     </record>
     <record>
      <date>19/02/2013</date>
      <people>29</people>
     </record>
     <record>
      <date>09/07/2013</date>
      <people>86</people>
     </record>
     <record>
      <date>30/04/2013</date>
      <people>35</people>
     </record>
     <record>
      <date>21/01/2012</date>
      <people>4</people>
     </record>
     <record>
      <date>26/06/2013</date>
      <people>88</people>
     </record>
     <record>
      <date>17/04/2013</date>
      <people>55</people>
     </record>
     <record>
      <date>04/10/2011</date>
      <people>38</people>
     </record>
     <record>
      <date>20/03/2013</date>
      <people>38</people>
     </record>
     <record>
      <date>19/05/2013</date>
      <people>91</people>
     </record>
     <record>
      <date>28/08/2011</date>
      <people>73</people>
     </record>
     <record>
      <date>31/08/2011</date>
      <people>65</people>
     </record>
     <record>
      <date>11/03/2013</date>
      <people>88</people>
     </record>
     <record>
      <date>10/06/2013</date>
      <people>78</people>
     </record>
     <record>
      <date>03/07/2013</date>
      <people>8</people>
     </record>
     <record>
      <date>08/10/2012</date>
      <people>16</people>
     </record>
     <record>
      <date>19/03/2012</date>
      <people>74</people>
     </record>
     <record>
      <date>28/09/2012</date>
      <people>49</people>
     </record>
     <record>
      <date>29/07/2013</date>
      <people>51</people>
     </record>
     <record>
      <date>05/10/2012</date>
      <people>60</people>
     </record>
     <record>
      <date>18/02/2012</date>
      <people>63</people>
     </record>
     <record>
      <date>03/09/2011</date>
      <people>45</people>
     </record>
     <record>
      <date>30/12/2011</date>
      <people>76</people>
     </record>
     <record>
      <date>11/04/2013</date>
      <people>96</people>
     </record>
     <record>
      <date>15/06/2012</date>
      <people>55</people>
     </record>
    </records>;
   
   private var minDate:Date = null;
   private var maxDate:Date = null;
   
   private var minSelDate:Date = null;
   private var maxSelDate:Date = null;
   
   private var dateCollection:ArrayCollection;
   
   protected function completeHandler(event:FlexEvent):void
   {
    // Parsing the xml data into ArrayCollection
    var objArray:ArrayCollection = new ArrayCollection();
    var tempObj:Object;
    var dateArray:Array;
    var tempDate:Date;
    for(var i:int = 0; i < myData.record.length(); i ++)
    {
     tempObj = new Object();
     dateArray = String(myData.record[i].date).split("/");
     //Convert the date data into a Date Object
     tempDate = new Date(dateArray[2], 
      Number(dateArray[1]) - 1, 
      dateArray[0]);
     parseDate(tempDate);
     tempObj.date = tempDate;
     tempObj.time = tempDate.time;
     tempObj.people = myData.record[i].people;
     objArray.addItem(tempObj);
    }
     
    // Create the new series and set its properties.
    var localSeries:LineSeries = new LineSeries();
    localSeries.dataProvider = objArray;
    localSeries.yField = "people";
    localSeries.xField = "date";
    
    // 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 creating the options for the combo box or
    //drop down menu over here.
    dateCollection = new ArrayCollection();
    tempDate.time = minDate.time;
    var tempDate2:Date = new Date();
    tempDate2.time = maxDate.time;
    tempDate2.date = 1;
    tempDate2.month += 1;
    while (tempDate.time <= tempDate2.time)
    {
     tempObj = new Object;
     tempObj.label = dateFormatter(tempDate);
     tempObj.date = tempDate.time;
     dateCollection.addItem(tempObj);
     tempDate.month += 1;
    }
    cb1.dataProvider = dateCollection;
    cb1.selectedIndex = 0;
    cb2.dataProvider = dateCollection;
    cb2.selectedIndex = dateCollection.length - 1;
    
    //Assigning the Minimum and the Maximum value
    //of the horizontal axis
    dateAxis.minimum = minDate;
    dateAxis.maximum = maxDate;
   }
   
   //This function will return a string based on the
   //Date format DD/MM/YYYY.
   private function dateFormatter(tempDate:Date):String
   {
    var fmt:DateFormatter = new DateFormatter();
    fmt.formatString = "DD/MM/YYYY";
    return fmt.format(tempDate);
   }
   
   //This function will be used in finding the minimum
   //and the maximum Date of the data. And based on the
   //minimum Date, we will round off to the first day
   //of the month and last day of the month for the
   //maximum date.
   private function parseDate(tempDate:Date):void
   {
    if(minDate == null)
    {
     minDate = new Date();
     minDate.time = tempDate.time;
     minDate.date = 1;
    }else{
     if(minDate.time > tempDate.time)
     {
      minDate.time = tempDate.time;
      minDate.date = 1;
     }
    }
    if(maxDate == null)
    {
     maxDate = new Date();
     maxDate.time = tempDate.time;
     maxDate.date = 1;
     maxDate.month += 1;
     maxDate.date = 0;
    }else{
     if(maxDate.time < tempDate.time)
     {
      maxDate.time = tempDate.time;
      maxDate.date = 1;
      maxDate.month += 1;
      maxDate.date = 0;
     }
    }
   }
   
   //We are customizing the datatip / tool tip of the
   //chart data.
   public function myDataTipFunction(e:HitData):String {
    var s:String = "";
    var tempDate:Date = e.item.date as Date;
    s += "Date: " + dateFormatter(tempDate) + "<br>";
    s += "No. of People: " + e.item.people;
    return s;
   }
   
   //Upon changing the values of the combobox, we will
   //set the minimum and maximum data of the chart 
   //based on the combobox selections
   protected function changeHandler(event:ListEvent):void
   {
    minSelDate = new Date();
    minSelDate.time = cb1.selectedItem.date;
    maxSelDate = new Date();
    maxSelDate.time = cb2.selectedItem.date;
    if(minSelDate.time < maxSelDate.time)
    {
     dateAxis.minimum = minSelDate;
     dateAxis.maximum = maxSelDate;
    }else{
     dateAxis.minimum = maxSelDate;
     dateAxis.maximum = minSelDate;
    }
   }
   
   //Upon clicking on the 'Reset' button, we will
   //update the values of the comboxbox and the chart.
   protected function clickHandler(event:MouseEvent):void
   {
    cb1.selectedIndex = 0;
    cb2.selectedIndex = dateCollection.length - 1;
    dateAxis.minimum = minDate;
    dateAxis.maximum = maxDate;
   }
   
  ]]>
 </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:horizontalAxis>
     <mx:DateTimeAxis dataUnits="days" id="dateAxis" 
          alignLabelsToUnits="true"/> 
    </mx:horizontalAxis>
   </mx:LineChart>
  </mx:HBox>
  <mx:HBox width="100%" horizontalAlign="center">
   <mx:Label text="Display Data between"/>
   <mx:ComboBox id="cb1" change="changeHandler(event)"/>
   <mx:Label text="and"/>
   <mx:ComboBox id="cb2" change="changeHandler(event)"/>
  </mx:HBox>
  <mx:HBox width="100%" horizontalAlign="center">
   <mx:Button label="Reset" click="clickHandler(event)"/>
  </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, August 4, 2012

Flex: Mac OS X, Mouse Wheel Detection

For some reason, mouse wheel scrolling doesn't really work on a Mac. Therefore after doing a bit of Googling or searching on the Internet, I finally found an ideal solution to my troubles.

* Click here for the demo that was created by pixelbreaker.
^ Click here for the post on Mac OS X, Mouse Wheel Detection by pixelbreaker.