Saturday, February 4, 2012

AS3: Valid Date Validator + ASDoc

I used to search over the web for a AS3 date validator back then and after spending some time searching and trying, I am going to share the class that I have written in the past with you. XD
(Note: By the way I have added a bit of extra stuff in the AS3 file. Take a look and it might turn out to be pretty handy in code writing in the future. :D)

The following would be the source file of my Main Application in Flex.
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" 
    layout="absolute"
     creationComplete="creationCompleteHandler(event)">
 
 <mx:Script>
  <![CDATA[
   import com.date.DateChecker;
   
   import mx.events.FlexEvent;
   
   //String to store the minimum year
   private var tempTxtMin:Number;
   
   //This function will be executed onve the button have
   //been clicked.
   protected function button1ClickEvent(event:MouseEvent):void
   {
    if(txtMin.text == "")
    {
     tempTxtMin = -1;
    }else{
     tempTxtMin = Number(txtMin.text);
    }
    //The following will check the given fields and
    //check if they were valid dates.
    lblResult.text = digestErrorIntoString(
     DateChecker.shortStrDateChecker(txtDay.text,
     txtMonth.text,
     txtYear.text,
     tempTxtMin));
    lblResult1.text = digestErrorIntoString(
     DateChecker.strDateChecker(txtDate.text,
     "/",
     tempTxtMin));
    lblResult2.text = digestErrorIntoString(
     DateChecker.strDateChecker(txtDate1.text,
      "-",
      tempTxtMin));
   }
   
   //Base on the the result that you are getting in
   //DateChecker.strDateChecker or DateChecker.shortStrDateChecker
   //output a string for the respective results
   private function digestErrorIntoString(error:int):String
   {
    var resultStr:String = "";
    switch(error)
    {
     case 0:
      resultStr = "This is a valid Date.";
      break;
     case 1:
      resultStr = "Please enter a numeric number " +
       "for the day of the month.";
      break;
     case 2:
      resultStr = "Please enter a numeric number " +
      "for the month of the year.";
      break;
     case 3:
      resultStr = "Please enter a numeric number " +
      "for the year that you are query.";
      break;
     case 4:
      resultStr = "Please enter a date between 1 - 31.";
      break;
     case 5:
      resultStr = "Please enter a month between 1 - 12.";
      break;
     case 6:
      resultStr = "Please enter a year that is greater " +
       "than " + String(tempTxtMin) + ".";
      break;
     case 7:
      resultStr = "This date doesn't exist.";
      break;
     case 8:
      resultStr = "Please enter the date according to the" +
       " format that was shown in the above.";
      break;
    }
    return resultStr;
   }
   
   //Upon Creation Complete of this class, populate some content.
   //And do a check on the fields.
   protected function creationCompleteHandler(event:FlexEvent):void
   {
    // TODO Auto-generated method stub
    txtMin.text = "1960";
    txtDay.text = "9";
    txtMonth.text = "8";
    txtYear.text = "1965";
    txtDate.text = "9/8/1959";
    txtDate1.text = "30-2-2012";
    button1ClickEvent(null);
   }
   
  ]]>
 </mx:Script>
 
 <mx:VBox width="100%" height="100%" verticalGap="10"
    horizontalAlign="center"
    verticalAlign="middle">
  <mx:HBox width="100%" horizontalAlign="center"
     horizontalGap="0">
   <mx:Label text="Minimum Year Allow:"/>
   <mx:TextInput id="txtMin" restrict="0-9" maxChars="4"/>
  </mx:HBox>
  <mx:HBox width="100%" horizontalAlign="center"
     horizontalGap="0">
   <mx:Label text="Enter a date:"/>
   <mx:TextInput id="txtDay" restrict="0-9" maxChars="2"/>
   <mx:Label text="/"/>
   <mx:TextInput id="txtMonth" restrict="0-9" maxChars="2"/>
   <mx:Label text="/"/>
   <mx:TextInput id="txtYear" restrict="0-9" maxChars="4"/>
   <mx:Label text="(Ex: DD/MM/YYYY)"/>
  </mx:HBox>
  <mx:HBox width="100%" horizontalAlign="center"
     horizontalGap="0">
   <mx:Label text="Result of the above:"/>
   <mx:Label id="lblResult"/>
  </mx:HBox>
  <mx:HBox width="100%" horizontalAlign="center"
     horizontalGap="0">
   <mx:Label text="Enter a date:"/>
   <mx:TextInput id="txtDate" restrict="0-9/"/>
   <mx:Label text="(Ex: DD/MM/YYYY)"/>
  </mx:HBox>
  <mx:HBox width="100%" horizontalAlign="center"
     horizontalGap="0">
   <mx:Label text="Result of the above:"/>
   <mx:Label id="lblResult1"/>
  </mx:HBox>
  <mx:HBox width="100%" horizontalAlign="center"
     horizontalGap="0">
   <mx:Label text="Enter a date:"/>
   <mx:TextInput id="txtDate1" restrict="0-9 \-"/>
   <mx:Label text="(Ex: DD-MM-YYYY)"/>
  </mx:HBox>
  <mx:HBox width="100%" horizontalAlign="center"
     horizontalGap="0">
   <mx:Label text="Result of the above:"/>
   <mx:Label id="lblResult2"/>
  </mx:HBox>
  <!-- Upon clicking on this button, 
  run the event 'button1ClickEvent'-->
  <mx:Button label="Check Now" click="button1ClickEvent(event)"/>
 </mx:VBox>
</mx:Application>

and here comes the AS3 Date checker class

package com.date
{
 public class DateChecker
 {
  public function DateChecker()
  {
  }
  
  /**
   * Used to check if the given string is a valid date
   * @param str - the string than you are checking 
   * for a valid date
   * @param divider - a string that will be used as a 
   * divider for str
   * @param minYear - the minimum year than the user 
   * can enter
   * @return one of the below integer (0-8)
   *   
0 - valid date *
1 - Invalid day (day must be a numerical value) *
2 - Invalid Month (month must be a numerical value) *
3 - Invalid Year (year must be a numerical value) *
4 - Invalid day (day must be in a range of 1 - 31) *
5 - Invalid Month (month must be in a range of 1-12) *
6 - Invalid Year (year must be > than the * minYear specified) *
7 - Date doesn't exist *
8 - the paramter str is not in the correct format */ public static function strDateChecker(str:String, divider:String = "/", minYear:Number = -1):int { var _strArray:Array = String(str).split(divider); //If the array has more than 3 items (e.g. 11/11/20/11) //it is not a valid date format, return error code 8 if(_strArray.length != 3) { return 8; }else{ return shortStrDateChecker(_strArray[0], _strArray[1], _strArray[2], minYear); } } /** * Used to check if the given strings turn out to be * a valid date * @param day - the day of the date that you are checking * in string format * @param month - the month of the date that you are checking * in string format * @param year - the year of the date that you are checking * in string format * @param minYear - the minimum year than the user * can enter * @return one of the below integer (0-8) *
0 - valid date *
1 - Invalid day (day must be a numerical value) *
2 - Invalid Month (month must be a numerical value) *
3 - Invalid Year (year must be a numerical value) *
4 - Invalid day (day must be in a range of 1 - 31) *
5 - Invalid Month (month must be in a range of 1-12) *
6 - Invalid Year (year must be > than the * minYear specified) *
7 - Date doesn't exist *
8 - the paramter day, month and * year is not given in the correct format */ public static function shortStrDateChecker(day:String, month:String, year:String, minYear:Number = -1):int { var _day:Number = Number(day); var _month:Number = Number(month); var _year:Number = Number(year); var _date:Date = new Date(); //if all 3 given parameters are either strings //or empty, return error code 8 if((isNaN(_day) || day == "") && (isNaN(_month) || month == "") && (isNaN(_year) || year == "")) { return 8; } //if given date is a String, return error code 1 if(isNaN(_day)) { return 1; } //if given month is a String, return error code 2 if(isNaN(_month)) { return 2; } //if given year is a String, return error code 3 if(isNaN(_year)) { return 3; } _month = Number(_month - 1); //if given day is a > 31 and < 0, return error code 4 if(_day > 31 || _day <= 0) { return 4; } //if given month is a > 12 and < 0, return error code 5 if(_month > 11 || _month < 0) { return 5; } //if given year is bigger than minYear, return error code 6 if(minYear != -1) { if(_year < minYear) { return 6; } } _date.fullYear = _year; _date.month = _month; _date.date = _day; //if the temp date and the given date doesn tally //, return error code 7 if(_date.date != _day || _date.month != _month || _date.fullYear != _year) { return 7; } return 0; } } }
* Click here to view the demo of this example.
^ Click here for the source files of this demo.

Wednesday, January 18, 2012

Flash AS3 + PHP: Publishing your flash contents into a PDF file (2)

Last week, I have shown you how to create a downloadable PDF using Flex + PHP + the Alive PDF library. As for this week, I shall move on to the step of printing out & breaking up a big datagrid into multiple pages.

The following would be the source file of my Main Application in Flex.
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
    creationComplete="creationCompleteHandler(event)">
 <mx:Script>
  <![CDATA[
   //Import the classes that are needed.
   import com.extentPDF.ExtendingPDF;
   
   import mx.collections.ArrayCollection;
   import mx.controls.dataGridClasses.DataGridColumn;
   import mx.events.FlexEvent;
   
   //Array to store the random data that I'm going to create
   private var dataArray:Array = new Array();
   private var dataColArray:ArrayCollection = new ArrayCollection();
   
   //Array to store the column sequence
   private var dgColumns:Array = new Array();
   
   protected function creationCompleteHandler(event:FlexEvent):void
   {
    //Add the respective column names into the array.
    dgColumns.push(new DataGridColumn("Name"));
    dgColumns.push(new DataGridColumn("Description"));
    dgColumns.push(new DataGridColumn("Price"));
    dgColumns.push(new DataGridColumn("Unit"));
    //Set the columns of the datagrid.
    dgDisplay.columns = dgColumns;
    
    //Create random data
    var j:int = 0;
    var tempObject:Object;
    for(var i:int = 1; i <= 100; i ++)
    {
     tempObject = new Object();
     if(i % 2 == 1)
     {
      tempObject.Name = "Item " + i;
     }else{
      tempObject.Name = "Product " + i;
     }
     tempObject.Price = "S$" + i;
     j = Math.round(Math.random() * 100);
     tempObject.Unit = i * j;
     tempObject.Description = "Description " + i;
     dataArray.push(tempObject);
    }
    //Pass the data into the datagrid
    dataColArray.source = dataArray;
    dgDisplay.dataProvider = dataColArray;
   }
   
   //Upon clicking on the button, make a downloadable pdf.
   protected function clickHandler(event:MouseEvent):void
   {
    saveContent();
   }  
   
   //Function that will be creating the downloadable PDF
   //with the help of PHP
   private function saveContent():void
   {
    //Create a new instance of ExtendingPDF class.
    var tempPDF:ExtendingPDF = new ExtendingPDF();
    //Add it to this application.
    this.addChild(tempPDF);
    this.validateNow();
    
    //Specify the first row that you are displaying
    var start:int = 0;
    //Specify the last row that you are displaying
    var end:int = 1;
    //Used to specify the row number of the data
    var row:int = 0;
    //Array to create a reference to the 'dataArray'
    //based on the start and the end
    var dummyArray:Array;
    //Array to store the result of the check upon
    //the PDF
    var checkResult:Array = null;
    //Should be add the last known good view to the PDF? 
    var mustInsertPrev:Boolean = false;
    //Loop through all the rows of the 'dataArray'
    //Add the view into the PDF if the view can fit in
    //else keep on adding a new row until it reach a point
    //where the new row cannot be added and then add the 
    //last known good view into the PDF.
    while(end <= dataArray.length)
    {
     dummyArray = new Array();
     row = 0;
     for(var i:int = start; i < end; i ++)
     {
      dummyArray[row] = dataArray[i];
      row ++;
     }
     dataColArray.source = dummyArray;
     dgDisplay.dataProvider = dataColArray;
     dgDisplay.verticalScrollPolicy = "off";
     dgDisplay.height = dgDisplay.headerHeight +
      dgDisplay.measureHeightOfItems(start, end - start);
     dgDisplay.validateNow();
     mustInsertPrev = false;
     checkResult = tempPDF.checkContentSize2PDFPage(dgDisplay);
     if(checkResult[0] == 1)
     {
      if((start + 1) == end)
      {
       tempPDF.addPage();
       checkResult = tempPDF.checkContentSize2PDFPage(dgDisplay);
       if(checkResult[0] == 0)
       {
        mustInsertPrev = false;
       }else{
        mustInsertPrev = true;
       }
      }else{
       mustInsertPrev = true;
      }
      if(mustInsertPrev)
      {
       end --;
       dummyArray = new Array();
       row = 0;
       for(i = start; i < end; i ++)
       {
        dummyArray[row] = dataArray[i];
        row ++;
       }
       dataColArray.source = dummyArray;
       dgDisplay.dataProvider = dataColArray;
       dgDisplay.verticalScrollPolicy = "off";
       dgDisplay.height = dgDisplay.headerHeight +
        dgDisplay.measureHeightOfItems(start, end - start);
       dgDisplay.validateNow();
       tempPDF.addContent2PDFPage(dgDisplay);
       start = end;
       end ++;
      }
     }else{
      end ++;
      if(end > dataArray.length)
      {
       tempPDF.addContent2PDFPage(dgDisplay);
      }
     }
    }
    //Create the PDF file that can be downloaded
    tempPDF.createContent();
    //Restore everything back to the state before
    //the PDF was created.
    dataColArray.source = dataArray;
    dgDisplay.dataProvider = dataColArray;
    dgDisplay.verticalScrollPolicy = "auto";
    dgDisplay.height = 200;
    container.addChildAt(dgDisplay,0);
    this.removeChild(tempPDF);
    this.validateNow();
   }
   
  ]]>
 </mx:Script>
 <mx:VBox id="container" width="100%" height="100%" 
    horizontalAlign="center" verticalAlign="middle">
  <mx:DataGrid id="dgDisplay" height="200"/>
  <mx:Button label="Print Content Now!" click="clickHandler(event)"/>
 </mx:VBox>
</mx:Application>

A Custom Class that I had created to handle the printing...
package com.extentPDF
{
 import flash.display.DisplayObject;
 import flash.geom.Point;
 
 import mx.containers.Canvas;
 
 import org.alivepdf.display.Display;
 import org.alivepdf.layout.Layout;
 import org.alivepdf.layout.Mode;
 import org.alivepdf.layout.Orientation;
 import org.alivepdf.layout.Position;
 import org.alivepdf.layout.Resize;
 import org.alivepdf.layout.Size;
 import org.alivepdf.layout.Unit;
 import org.alivepdf.pages.Page;
 import org.alivepdf.pdf.PDF;
 import org.alivepdf.saving.Download;
 import org.alivepdf.saving.Method;
 
 public class ExtendingPDF extends Canvas
 {
  //Path to the Php file used to generate the pdf file
  private var phpUrl:String = "http://bestkirdape.freeiz.com/php/create.php";
  
  //File Name that I'm giving the pdf file
  private var strFilename:String = "PrintOut_Of_MultipleViewWithAlivePDF.pdf";
  
  private var myPDF:PDF;
  private var pdfHeight:int = 0;
  
  public function ExtendingPDF()
  {
   //Specify the settings of the PDF
   //In my case, I'm using a PORTRAIT view, a size of A4
   //and everything will be calculated in POINT.
   myPDF = new PDF(Orientation.PORTRAIT, 
    Unit.POINT, Size.A4);
   //Set the Display Mode of the PDF when it was opened.
   myPDF.setDisplayMode (Display.FULL_PAGE, Layout.SINGLE_PAGE);
   //Set the Margins (left, top, right, bottom)
   myPDF.setMargins(40,60,40,60);
   addPage();
  }
  
  //Create a new page into the PDF.
  public function addPage():void
  {
   var newPage:Page = new Page ( Orientation.PORTRAIT, 
    Unit.POINT, Size.A4 );
   //Add a Page to the PDF
   myPDF.addPage(newPage);
   pdfHeight = 0;
  }
  
  //This function is used to add the content into the current page
  public function addContent2PDFPage(content:DisplayObject):void
  {
   var resultArray:Array = checkContentSize2PDFPage(content);
   //Check if the content can fit into the current page
   //else need to create a new page
   if (resultArray[0] == 1)
   {
    addPage();
   }
   //Add the content into a Canvas first before adding into
   //the current page of the pdf.
   var tempContainer:Canvas = new Canvas();
   this.addChild(tempContainer);
   tempContainer.width = Math.floor(content.width) + 4;
   tempContainer.height = Math.floor(content.height) + 4;
   tempContainer.setStyle("backgroundAlpha",0);
   tempContainer.addChild(content);
   content.x = 0;
   content.y = 0;
   tempContainer.validateNow();
   this.validateNow();
   
   //Adds like a screen capture and capture a screen shot
   //of the content
   myPDF.addImage(tempContainer, new Resize(Mode.NONE, 
    Position.LEFT), 0, pdfHeight, (resultArray[1] as Point).x, 
    (resultArray[1] as Point).y);
   pdfHeight = pdfHeight + (resultArray[1] as Point).y + 10;
   
   //remove views that are not needed
   this.removeChild(tempContainer);
  }
  
  //This function is used to check whether the content 
  //can fit into the current page
  public function checkContentSize2PDFPage(content:DisplayObject):Array
  {
   var pageWidth:Number = myPDF.getCurrentPage().w - 80;
   var pageHeight:Number = myPDF.getCurrentPage().h - 120;
   var imgScaleFactor:Number = content.width/content.height;
   
   var pw:int = 0;
   var ph:int = 0;
   pw = Math.floor(pageWidth);
   ph = Math.floor(pw/imgScaleFactor);
   var tempArray:Array = new Array();
   var tempPoint:Point = new Point();
   tempPoint.x = pw;
   tempPoint.y = ph;
   
   if ((pdfHeight + ph) > pageHeight)
   {
    tempArray[0] = 1;
   }else{
    tempArray[0] = 0;
   }
   tempArray[1] = tempPoint;
   return tempArray;
  }  
  
  //Create the PDF file that can be downloaded
  public function createContent():void
  {
   myPDF.save( Method.REMOTE, phpUrl, Download.ATTACHMENT, strFilename);
  }   
 }
}

* Click here to view the demo of this example.
^ Click here for the source files of this demo.

~ Click here for the website of 'Alive PDF'.
- Click here for the Documentation of the classes of 'Alive PDF'.
** Click here for the older tutorials on 'Alive PDF'.

Sunday, January 15, 2012

Flash AS3 + PHP: Publishing your flash contents into a PDF file

With the release of Flash Player 10, you can easily create an image file to display all the contents into an image on the fly. But with the help of 'Alive PDF' and Php, you can actually create PDF on the fly.

The following would be a simple demo that I have created. The generated PDF will display 2 blocks of text. The first text would be a capture of the text view in the Flex Application and the second text was inserted into the PDF using the functions provided in the 'Alive PDF' API.

So let us take a look at some coding. :D
<?php

$method = $_GET['method'];
$name = $_GET['name'];

if ( isset ( $GLOBALS["HTTP_RAW_POST_DATA"] )) {
 
 // get bytearray
 $pdf = $GLOBALS["HTTP_RAW_POST_DATA"];
 
 // add headers for download dialog-box
 header('Content-Type: application/pdf');
 header('Content-Length: '.strlen($pdf));
 header('Content-disposition:'.$method.'; filename="'.$name.'"');
 echo $pdf;
 
}  else echo 'An error occured.';

?>
The above Php script was taken from the Alive PDF website.

The following would be the source file of my Main Application in Flex.
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
    creationComplete="creationCompleteHandler(event)"
    width="100%" height="100%">
 <mx:Script>
  <![CDATA[
   import mx.events.FlexEvent;
   
   import org.alivepdf.colors.RGBColor;
   import org.alivepdf.display.Display;
   import org.alivepdf.fonts.CodePage;
   import org.alivepdf.fonts.EmbeddedFont;
   import org.alivepdf.layout.Layout;
   import org.alivepdf.layout.Mode;
   import org.alivepdf.layout.Orientation;
   import org.alivepdf.layout.Position;
   import org.alivepdf.layout.Resize;
   import org.alivepdf.layout.Size;
   import org.alivepdf.layout.Unit;
   import org.alivepdf.pages.Page;
   import org.alivepdf.pdf.PDF;
   import org.alivepdf.saving.Method;
   
   //Some Dummy Text
   [Bindable]
   private var msg:String = "Lorem ipsum dolor sit amet, " +
    "consectetur adipiscing elit. Cras nec eros sit amet " +
    "dui sagittis volutpat pharetra et est. Curabitur " +
    "ultricies suscipit volutpat. Aenean feugiat " +
    "ullamcorper pellentesque. Nulla ut venenatis ligula. " +
    "Nam ornare est a odio condimentum bibendum. Sed " +
    "lorem est, tristique at gravida in, blandit vitae leo. " +
    "Etiam lobortis mi vel magna porta tempus. Suspendisse " +
    "in tortor non magna hendrerit vulputate id quis justo. " +
    "Integer vehicula tortor tortor. Cras consequat, tortor " +
    "in cursus consequat, risus justo vehicula arcu, eu " +
    "consequat dolor leo sed felis. In euismod mollis blandit. " +
    "Vivamus tempus rutrum lorem quis commodo. Suspendisse " +
    "condimentum lorem at risus eleifend porttitor. Nulla " +
    "molestie ipsum nec lacus convallis semper sed ut enim. " +
    "Curabitur arcu justo, imperdiet ac rutrum eget, porta " +
    "eget orci. Nulla aliquet tristique rutrum.";
   
   //Path to the Php file used to generate the pdf file
   private var phpUrl:String = "http://bestkirdape.freeiz.com/php/create.php";
   
   //File Name that I'm giving the pdf file
   private var strFilename:String = "PrintOut_Of_PlayingWithAlivePDF.pdf";
   
   //Specify the Embedded font used by the label, lblText
   [Embed( source="fonts/jokerman.TTF", mimeType="application/x-font", fontName="jokermanFont")]
   public var jokermanFont:Class;
   
   //Specify the Embedded font that I'm using in the print out
   [Embed( source="fonts/jokerman.TTF", mimeType="application/octet-stream")]
   public var jokerman_ttf:Class;
   [Embed( source="fonts/jokerman.afm", mimeType="application/octet-stream" )]
   public var jokerman_afm:Class;
   
   //Specify the Font Color
   private var textColor:uint = 0x000000;
   
   //Open up the pdf upon clicking on the button 'Print Content Now!'.
   protected function btnPrint_clickHandler(event:MouseEvent):void
   {
    printContent();
   }
   
   private function printContent():void
   {
    //This variable is needed to specify the Embedded font that
    //we are using
    var font:EmbeddedFont = new EmbeddedFont(
     new jokerman_ttf() as ByteArray
     , new jokerman_afm() as ByteArray
     , CodePage.CP1252
    );
    //Specify the settings of the PDF
    //In my case, I'm using a PORTRAIT view, a size of A4
    //and everything will be calculated in POINT.
    var myPDF:PDF = new PDF(Orientation.PORTRAIT, 
     Unit.POINT, Size.A4);
    //Set the Display Mode of the PDF when it was opened.
    myPDF.setDisplayMode ( Display.FULL_WIDTH );
    //Set the Margins (left, top, right, bottom)
    myPDF.setMargins(10,20,10,20);
    //Add a Page to the PDF
    myPDF.addPage();
    //Change the size of the view,, lblText and ...    
    lblText.width = (myPDF.getCurrentPage().w - 20);
    resizeMe(lblText);
    lblText.validateNow();
    //add it to the PDF
    myPDF.addImage(lblText,null,0,0); 
    //Set the Font of the PDF
    myPDF.setFont(font, lblText.getStyle("fontSize"));
    //Set the Color of the Text of the PDF
    myPDF.textStyle(new RGBColor(Number(textColor)));
    //Change the XY coordinates of the view that
    //I'm going to add
    myPDF.setXY(10, lblText.height + 20 + 10);
    //Create a Cell to display my text and centralised it
    myPDF.addMultiCell(myPDF.getMargins().width,
     lblText.getStyle("fontSize") + 6, msg, 0, "C", 0);
    //*********UPDATED***********
    //Download the PDF file
    //Need to add Download.ATTACHMENT as one of the parameters 
    //in order to download the pdf file.
    myPDF.save( Method.REMOTE, phpUrl, Download.ATTACHMENT, strFilename);
    //Revert the width of the view, lblText.
    lblText.width = 400;
    resizeMe(lblText);
    lblText.validateNow();
   }
   
   protected function creationCompleteHandler(event:FlexEvent):void
   {
    resizeMe(lblText);
   }
   
   //Used to resize the TextArea so that all the text
   //will be shown.
   private function resizeMe(field:TextArea) :void
   {
    field.validateNow();
    field.mx_internal::getTextField().autoSize = 
     TextFieldAutoSize.CENTER;
    field.height = field.mx_internal::getTextField().height;
   }   
   
  ]]>
 </mx:Script>
 <mx:VBox width="100%" verticalAlign="middle" 
    horizontalAlign="center" height="100%">
  <mx:TextArea id="lblText" wordWrap="true"
      backgroundAlpha="0"
      borderThickness="0"
      fontFamily="jokermanFont"
      color="{textColor}"
      text="{msg}" width="400" textAlign="center"/>
  <mx:Button click="btnPrint_clickHandler(event)"
       label="Print Content Now!"/>
 </mx:VBox>
</mx:Application>

* Click here to view the demo of this example.
^ Click here for the source files of this demo.

~ Click here for the website of 'Alive PDF'.
- Click here for the Documentation of the classes of 'Alive PDF'.
** Click here for the .adm file generator.
(Note: you need to upload a .ttf file before you can generate the .adm file.

Monday, January 2, 2012

A stupid font settings of Windows 7

Have you encounter the problem of starting up your Windows 7 and realised that all your Chinese or Korean or Japanese characters have turned into square boxes like the following, []? I have encounter it before and today I am going to share a possible fix for it.

Here are the steps:
  1. Click on the 'Start' button on the bottom left of the screen
  2. Click on 'Control Panel'
  3. Click on 'Appearance and Personalization'
  4. Click on 'Fonts'
  5. In the left pane, click on 'Font settings'
  6. Click on 'Control Panel'
  7. Make sure that the 'Hide fonts based on language settings' check box is not selected
  8. Restart your Laptop or PC and you are done.

* Click here to find out more.

Sunday, January 1, 2012

Flex: Converting your views into ByteArray

Probably they are times where you need to send image captures of the views in the Flex Application to one of your servers but how do you do that? As for this week, I am going to show you how to convert all your views into ByteArray before you convert them into base64 strings and send it to the server.

The following would be the source code for my demo.
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
    creationComplete="creationCompleteHandler(event)" 
    width="100%" height="100%">
 <mx:Script>
  <![CDATA[
   import mx.events.FlexEvent;
   //Need to import this class for capturing the view
   import mx.graphics.ImageSnapshot;
   
   //Array to stroe the data for the data grid
   private var arr:Array = new Array();
   private var arr1:Array = new Array();
   
   //Array to store data for the combobox
   private var arr_Content:Array = new Array();
   
   //ByteArray to store the captured image
   private var resultArray:ByteArray;
   
   //Upon clicking on the 'Main' button, 
   //change to the original state
   protected function btnMain_clickHandler(event:MouseEvent):void
   {
    this.currentState = "";
   }
   
   //Upon clicking on the 'Result' button, 
   //change to the 'result' view with the result Image
   protected function btnResult_clickHandler(event:MouseEvent):void
   {
    this.currentState = "result";
   }
   
   //Upon clicking on the 'Capture Now!' button, 
   //Capture the current look and feel of the selected item
   //in the combo box
   protected function btnCapture_clickHandler(event:MouseEvent):void
   {
    updateResult();
    this.currentState = "result";
   }
   
   //Function that create the ByteArray based on the selected item
   //in the combobox
   private function updateResult():void
   {
    resultArray = null;
    var imageSnap:ImageSnapshot = ImageSnapshot.captureImage(
     cmbViewName.selectedItem.data);
    resultArray = imageSnap.data as ByteArray;
   }
   
   //Upon creationComplete, let us populate the views with data
   protected function creationCompleteHandler(event:FlexEvent):void
   {
    var tempObj:Object;
    for(var i:int = 0; i < 8; i ++)
    {
     tempObj = new Object();
     for(var j:int = 0; j < 3; j ++)
     {
      tempObj["col" + (j+1)] = "Row " + (i + 1) 
       + " Col " + (j + 1); 
     }
     arr.push(tempObj);
    }
    dataGrid.dataProvider = arr;
    
    for(var i = 0; i < 20; i ++)
    {
     tempObj = new Object();
     for(var j = 0; j < 5; j ++)
     {
      tempObj["col" + (j+1)] = "Row " + (i + 1) 
       + " Col " + (j + 1); 
     }
     arr1.push(tempObj);
    }
    dataGrid1.dataProvider = arr1;
    
    this.validateNow();
    tempObj = new Object();
    tempObj.label = "Main Application";
    tempObj.data = viewAll;
    arr_Content.push(tempObj);
    tempObj = new Object();
    tempObj.label = "Top Panel";
    tempObj.data = viewBtnsPanel;
    arr_Content.push(tempObj);
    tempObj = new Object();
    tempObj.label = "Contents";
    tempObj.data = viewContent;
    arr_Content.push(tempObj);
    tempObj = new Object();
    tempObj.label = "1st Data Grid";
    tempObj.data = dataGrid;
    arr_Content.push(tempObj);
    tempObj = new Object();
    tempObj.label = "2nd Data Grid";
    tempObj.data = dataGrid1;
    arr_Content.push(tempObj);
    
    cmbViewName.dataProvider = arr_Content;
    this.validateNow();
    updateResult();
   }
   
   //Upon moving into the 'result' state, update the source 
   //of the image
   protected function state1_enterStateHandler(event:FlexEvent):void
   {
    // TODO Auto-generated method stub
    imgResult.source = resultArray;
   }
   
  ]]>
 </mx:Script> 
 <mx:states>
  <mx:State name="result" enterState="state1_enterStateHandler(event)">
   <mx:RemoveChild target="{cmbViewName}"/>
   <mx:RemoveChild target="{btnCapture}"/>
   <mx:RemoveChild target="{dataGrid}"/>
   <mx:RemoveChild target="{dataGrid1}"/>
   <mx:AddChild position="lastChild" relativeTo="{viewContent}">
    <mx:Image id="imgResult" width="100%" height="100%"
        scaleContent="false"/>
   </mx:AddChild>
  </mx:State>
 </mx:states>
 <mx:VBox width="100%" height="100%" verticalGap="10"
    left="10" right="10" top="10" bottom="10"
    id="viewAll">
  <mx:HBox width="100%" id="viewBtnsPanel">
   <mx:Button id="btnMain" label="Main" 
        click="btnMain_clickHandler(event)"/>
   <mx:Button id="btnResult" label="Result" 
        click="btnResult_clickHandler(event)"/>
   <mx:Spacer width="100%"/>
   <mx:ComboBox id="cmbViewName"/>
   <mx:Button id="btnCapture" label="Capture Now!" 
        click="btnCapture_clickHandler(event)"/>
  </mx:HBox>
  <mx:VBox id="viewContent" width="100%" height="100%" 
     verticalGap="10">
   <mx:DataGrid id="dataGrid" width="100%"/>
   <mx:DataGrid id="dataGrid1" width="100%" height="100%"/>
  </mx:VBox>
 </mx:VBox>
</mx:Application>

* Click here to view the demo of this example.
^ Click here for the source files of this demo.

Saturday, December 24, 2011

Flex: Changing the color of the background color of your Pop Ups

I have encountered situations when there's a need to have more than 1 type of background color in your Flex Application. Some Popups might need a black background with 50% opacity some might requires a background with 0% opacity, etc. One of the easiest way to change the background color of the popup will be the step of changing the global styles, but as your Flex Application gets more and more complex, manipulating with the global styles wouldn't be a recommended way of doing things. Hence, I'm going to show you another way of manipulating the background color of your popup today.

The following would be the source code of my main Application.


 
 
  global{
   modalTransparency:0;
   modalTransparencyBlur:0;
   modalTransparencyColor:0;
   modalTransparencyDuration:100;
  }
 
 
 


View that contains some buttons


 
 
  
 
 
 
 


Here comes the important part.
This would be my class that acts like a Pop Up background.
package com.popup
{
 import mx.containers.Canvas;
 import mx.core.Application;
 
 //This class acts as the background in the PopUpManager CLass
 public class PopUpBackground extends Canvas
 {
  public function PopUpBackground()
  {
   super();
   this.height = Application.application.height;
   this.width = Application.application.width;
   this.validateNow();
  }
 }
}

This would be my main class that will be replacing the use of PopUpManager.
package com.popup
{
 import flash.display.DisplayObject;
 
 import mx.collections.ArrayCollection;
 import mx.core.Application;
 import mx.core.IFlexDisplayObject;
 import mx.managers.PopUpManager;

 public class PopUpOverlay
 {
  /** Only one instance of the PopUpOverlay allowed **/
  private static var instance:PopUpOverlay;
  //This is used to store the various Pop Ups
  private var arrayPopupList:ArrayCollection = new ArrayCollection();
  
  public function PopUpOverlay(singletonEnforcer:SingletonEnforcer)
  {
  }
  
  public static function getInstance():PopUpOverlay
  {
   //Create an instance of PopUpOverlay
   if(instance == null) { 
    instance = new PopUpOverlay(new SingletonEnforcer()); 
   } 
   return instance; 
  }
  
  public function createPopUp(parent:DisplayObject, className:Class
    , modal:Boolean = true, backgroundColor:uint = 0xFFFFFF
    , alpha:Number = 0.5):Object
  {
   //If a parent view is not specified, create the 
   //popup on the main Application
   if(parent == null)
   {
    parent = Application.application as DisplayObject;
   }
   //Create the background of the Pop Up using PopUpBackground first
   var tempDisplayObject:* = PopUpManager.createPopUp(parent,PopUpBackground,modal);
   tempDisplayObject.setStyle("backgroundColor", backgroundColor);
   tempDisplayObject.setStyle("backgroundAlpha", alpha);
   this.arrayPopupList.addItem(tempDisplayObject);
   
   //Next, Create the real Pop Up specified by the className
   tempDisplayObject = PopUpManager.createPopUp(parent,className,modal);
   PopUpManager.centerPopUp(tempDisplayObject);
   this.arrayPopupList.addItem(tempDisplayObject);
   return tempDisplayObject;
  }
  
  public function removePopUp():void
  {
   //Remove the create Pop Up View first
   if(this.arrayPopupList.length > 0)
   {
    var tempDisplayObject:IFlexDisplayObject = this.arrayPopupList.removeItemAt(this.arrayPopupList.length - 1) as IFlexDisplayObject;
    PopUpManager.removePopUp(tempDisplayObject);
   }
   //Followed by the background
   if(this.arrayPopupList.length > 0)
   {
    tempDisplayObject = this.arrayPopupList.removeItemAt(this.arrayPopupList.length - 1) as IFlexDisplayObject;
    PopUpManager.removePopUp(tempDisplayObject);
   }
  }
 } 
}
class SingletonEnforcer{};   

* Click here to view the demo of this example.
^ Click here for the source files of this demo.

Friday, December 16, 2011

Flash: Playing with preloaders

I remember the days where I was trying to work around preloaders and trying to force them to display a numerical status of 0 - 100%. Especially, when you are using a in-house server and it just happens that your server is using the same connection as your laptop your desktop, you will never get to see your preloader running. Especially when there are more and more flash sites out there with interesting interactive preloaders, it would be nice to have a COOL preloader up and running. By the way, here's my solution to tackle around and ensure that you will be getting a preloader all the time.

By the way I will be working base on my demos a few weeks ago.

Here's the source file for the preloader.
package com.stretchingDemo
{
 import com.util.preloader.*;
 
 import flash.display.MovieClip;
 import flash.events.Event;
 
 public class Index extends MovieClip
 {
  //To preload your preloader file, which is this file.
  private var tempMainPreloader:MainPreloader;
  //To preload your content file
  private var tempSectionPreloader:SectionPreloader;
  private var _preloader_mc:MovieClip;
  
  //Variable to store your current preloading status 
  private var _preloadNum:Number = 0;
  //Variable to store the highest numerical number to display
  private var _maxPreloadNum:Number = 0;
  
  public function Index():void
  {
   //Start preloading this file
   tempMainPreloader = new MainPreloader(this,5);
   _preloader_mc = this.getChildByName("preloader_mc") as MovieClip;
   this.addEventListener(Event.ENTER_FRAME, progress0Handler);
  }
  
  //function executed when the preloader had finish loading
  private function progress0Handler(event:Event):void
  {   
   var str:String = String((tempMainPreloader.currentProgress)); 
   //Update your text field to display the loading status
   this._preloader_mc.preloader_txt.text = str;
   
   if(tempMainPreloader.currentProgress == tempMainPreloader.maxProgress){ 
    this.removeEventListener(Event.ENTER_FRAME, progress0Handler); 
    loadSubContent(); 
   }
  } 
  
  //function to load the main swf
  public function loadSubContent():void
  {
   //Grab the main swf that you want to load.
   //Usually I will call the prelaoder file 'load_XXX' 
   //where 'XXX' will be the filename of the main swf file. 
   //On top of this, this will help you to structure your 
   //folders properly too. As you can see will my swf files
   //are in the swf folder and my html file is on the root folder.
   var tempStr = String(this.root.loaderInfo.loaderURL).replace(/%5F/gi,"_");
   var tempArray = tempStr.split("load_");
   this.addEventListener(Event.ENTER_FRAME, preloadContentEvent);   
   tempSectionPreloader = new SectionPreloader(tempArray[0] + tempArray[1] ,95);
   tempSectionPreloader.addEventListener(
SectionPreloader.SectionContentLoading, progressHandler2);
  }
  
  //function to update the numerical count on the preloader field
  //And show the main content when the numerical count reaches 100
  private function preloadContentEvent(event:Event):void
  {
   if(_preloadNum < _maxPreloadNum)
   {
    _preloadNum ++;
   }
   this._preloader_mc.preloader_txt.text = Number(_preloadNum + tempMainPreloader.currentProgress);
   if(_preloadNum == _maxPreloadNum && _maxPreloadNum == tempSectionPreloader.maxProgress && tempSectionPreloader.getContent() != null){ 
    tempSectionPreloader.removeEventListener(
SectionPreloader.SectionContentLoading, progressHandler2);
    this.removeEventListener(Event.ENTER_FRAME, preloadContentEvent);  
    this.removeChild(_preloader_mc);
    this.addChild(tempSectionPreloader);
   } 
  }
  
  //function that will be called to update the progress of the loading 
  //of the file when the main file was loading and finish loading
  private function progressHandler2(evt:Event){ 
   _maxPreloadNum = tempSectionPreloader.currentProgress;
  }  
 }
}
* Click here to view the previous example.
^ Click here to view the demo of this example.
~ Click here for the source files of this demo.