Thursday, October 15, 2009

Flex callLater()

The other I was working on a Form container. Where in I have few form items and a default button for submit. I was also using validators for validating the fields.
The validators are bound to the input fields, so that the 'errorString' is automatically populated for each input field. I do have submitHandler() to be triggered when the button is clicked. The order of event execution is not as desired by me. First the custom handler is triggered, next the event in the validators are triggered, which is vice-versa I wanted.

I'll put it in code what I mean:


<mx:Script>
 //this function triggers after the validations are completed
 private function onSubmit( p_evt : MouseEvent = null):void
 {
  trace(firstName.errorString);
  trace(lastName.errorString);
 }
</mx:Script>
<mx:StringValidator minLength="2" required="true" property="text" trigger="{submitBtn}" triggerEvent="click" source="{firstName}" id="firstNameValidator" />
<mx:StringValidator minLength="2" required="true" property="text" trigger="{submitBtn}" triggerEvent="click" source="{lastName}"/>

<mx:Form width="100%" height="100%" paddingLeft="5" paddingRight="5" id="form" defaultButton="{submitBtn}">
  
 <mx:FormItem label="First Name*">
     <mx:TextInput width="115" editable="true" color="0x000000" id="firstName" styleName="formInput" />
 </mx:FormItem>
 
 <mx:FormItem label="Last Name*">
     <mx:TextInput width="115" color="0x000000" id="lastName" styleName="formInput"/>
 </mx:FormItem>
 
 <mx:FormItem label="Last Name*">
  <mx:Button click="callLater(onSubmit);" buttonMode="true" id="submitBtn" />
 </mx:FormItem>
</mx:Form>

Flex Combobox styles

Setting styles to combobox is not just as simple as assigning a 'styleName' property.
The style doesn't apply that easily to the 'prompt' text. By default the font weight is bold and it screws up if the font specified in the styles doesn't have a bold face.

Ideally, it can be like this:
ComboBox {
cornerRadius: 0;
fillAlphas: 1, 1, 1, 1;
fillColors: #ffffff, #ffffff, #ffffff, #eeeeee;
font-family: Avangmb;
font-size: 11;
dropdownStyleName: comboBoxDropdownStyles;
}

.comboBoxDropdownStyles {
fontFamily: AVGARDM;
fontWeight: normal;
}

Wednesday, September 30, 2009

org chart source code

org chart source code

updateDisplayList

Flex again proved to be a strange/weird technology for its instable behaviour.

Never try to override the updateDisplayList() of Application container.
When you override this method, the percentWidth/percentHeight properties doesn't work properly. I was trying to use the graphics object for some background and this enforces the percentWidth/percentHeight not to work properly.

There are two case scenarios:
1) When you don't call the super()

override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
super.updateDisplayList(unscaledWidth, unscaledHeight );
this.graphics.lineStyle(1, 0xE51745 );
this.graphics.beginFill(0x341264);
this.graphics.drawRect(0,0, 32, unscaledHeight);
this.graphics.endFill();

this.graphics.beginFill(0xE51745);
this.graphics.drawRect(32,0, unscaledWidth, unscaledHeight);
this.graphics.endFill();
}

In this instance, the graphics object doesn't draw anything.

2) When super() is not called:
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{

this.graphics.lineStyle(1, 0xE51745 );
this.graphics.beginFill(0x341264);
this.graphics.drawRect(0,0, 32, unscaledHeight);
this.graphics.endFill();

this.graphics.beginFill(0xE51745);
this.graphics.drawRect(32,0, unscaledWidth, unscaledHeight);
this.graphics.endFill();
}

In this instance, the graphics object draws the background but the percentWidth/percentHeight fails, ofcourse, for apparent reasons.

Tuesday, August 25, 2009

Flex Library SWC and AS Doc generation - Tips & Tricks

This is just an addition to the already many existing tips on the web. These are few tips that helped me get resolved some of ASDoc errors.

1) CSS – All the paths to images/swf/external assets should be resolved to absolute. Relative paths are recognised by the asdoc/compc tools.
2) build.xml spaces – Sometimes the spaces in the file paths are not resolved; enclose them in quotes.
3) external-library-path – To give you understanding, whatever libraries referenced here are excluded from compiling into swf/asdoc/swc.
4) When creating a library SWC ensure to mention source-path argument, all the files you are referencing should be in the source path. Else the external assets are recognised by the compc.

Friday, August 21, 2009

AS Doc Generation with Ant

Ant has become my favourite tool again after started using it in flex. I remember using while I was working on java stuff. Now I start to compile my flex apps and libraries with Ant, though I use Flex builder. I just ignore the flex builder problems/errors and look up for the Ant tasks console. Because, flex builder can ignore few errors/warnings out of the project scope. Compiling with Ant/command-line is stricter and helps your code keep clean. Here I am going to describe primarily about how to generate AS docs for a flex project, it can be a library project as well. Though, I focus on the Ant build tool, pretty much the commands can be used on the command-line compiler also.

1) Install ANT in your flex builder. If you are not sure how to install, follow this link. http://www.adobe.com/devnet/flex/articles/flex_ant_pt1.html

http://www.adobe.com/devnet/flex/articles/flex_ant_pt2.html I recommend you to go through both the parts of the tutorial as it contains valuable information as how to install ANT and get started.

2) If you are ready with ANT, you should be having two file in the root directory of your project.

a. build.xml

b. build.properties

My build.properties file typically looks like this:

# change this to your Flex SDK directory path

FLEX_HOME=C:/Program Files/Adobe/Flex Builder 3/sdks/3.3.0

# defines the Flex framework files location

FLEX_FRAMEWORK = ${FLEX_HOME}/frameworks/libs

# this points to your project's src directory

# {$basedir} is a default variable that can be used in any Ant script

# and it points to the project's root folder [ Flex_Ant_Tasks ] in this case

SRC_DIR =${basedir}/src

# points to the project's libs directory

LIBS_DIR =${basedir}/libs

# this is the folder we want to publish the swf to

DEPLOY_DIR = ${basedir}/bin-release

#this property defines the doc directory, which will store your created ASDocs later in the article

DOC_DIR =${basedir}/asdocs

# defines the title for your ASDoc pages

DOC_TITLE ="Project Documentation"

# defines the footer for your ASDoc pages

DOC_FOOTER = "Copyright© 2009"

# points to your asdoc.exe for ASDoc creation later

asdoc.exe =${FLEX_HOME}/bin/asdoc.exe

Note this parameter in your build.properties file for storing your AS doc.:

#this property defines the doc directory, which will store your created ASDocs later in the article

DOC_DIR = ${basedir}/asdocs

3) Now in your build.xml , add this bit to ensure that you delete the existing directory and create a new directory for AS docs:

<target name="Create AS Doc DIR">

<delete dir="${DOC_DIR}" />

<mkdir dir="${DOC_DIR}" />

</target>

4) Here comes the main bit code for AS doc generation:

<target name="Create AS Docs" depends="Create AS Doc DIR">

<exec executable="${asdoc.exe}" failonerror="false">

<arg line='-source-path ${SRC_DIR}' />

<arg line='-external-library-path ${LIBS_DIR}' />

<arg line='-doc-classes MyFrameworkClasses' />

<arg line='-warn-level-not-supported=false'/>

<arg line='-main-title ${DOC_TITLE}' />

<arg line='-window-title ${DOC_TITLE}' />

<arg line='-footer ${DOC_FOOTER}' />

<arg line='-output ${DOC_DIR}' />

<arg line='-strict=false' />

</exec>

</target>

The <exec> sets the asdoc.exe file to run AS doc engine from the flex builder directory. This token should have been initialized in the build.properties file. Look into the build.properties file, if not it should be like this:

# points to your asdoc.exe for ASDoc creation later

asdoc.exe =${FLEX_HOME}/bin/asdoc.exe

<arg line='-source-path ${SRC_DIR}' /> - Set the source-path with src directory of your project

<arg line='-external-library-path ${LIBS_DIR}' /> - This is where you set all your external libraries, which are compiled into SWC. AS Docs are not generated for these libraries.

<arg line='-doc-classes MyProjectClasses' /> -(There’s also an alternative command to achieve this.) This line implies which classes should you generate AS doc for. This is the trickier bit and this is how Adobe compiles the framework classes. MyProjectClasses.as file is a dummy class that stores the references for the classes you want to generate. It can be something like this:

/**

* It is a good practice to maintain this class at the root of src directory.

* MyProjectClasses.as

*

*/

package

{

/**

* @private

*/

internal class IBFrameworkClasses

{

import com.classA; classA;

import com.classB; classB;

import com.classC; classC;

import com.classD; classD;

}

}

Specify, all of your classes you want to document here. This seems to be frightening task, but I suggest this approach as it is a onetime task and really helps you maintain all your classes.

Ok, you are not comfortable!! Take this approach...

<arg line='-doc-sources ${SRC_DIR}' /> - This command is simple and straight forward, it documents all the classes in the src directory. I know that is what you want!!! In this approach, ensure that all the class libraries are supplies in SWC format, else you would run into creating documentation for all n number of classes.

Next few commands should be pretty straight forward, labelling the documentation and storing the AS docs in the DOC_DIR.

Wednesday, July 29, 2009

Flex Layout Techniques - Part II

I am going to give you an important tip, for people who are new Flex/Flash Technology.

The scaleX and scaleY properites can take negative values as well...

//draw a box
var box:Sprite = new Sprite();
box.graphics.beginFill(0x000000);
box.graphics.drawRect(0,0,50,50);
box.graphics.endfil();

// reverses the box in the vertical direction
box.scaleY = -1;

// reverses the box in the horizontal direction
box.scaleX = -1;

Tuesday, May 26, 2009

Something hidden about the Container

Although at the level of a Flash DisplayObjectContainer, all
children are equal, in a Flex Container some children are "more
equal than others". (George Orwell, "Animal Farm")

In particular, Flex distinguishes between content children and
non-content (or "chrome") children. Content children are the kind
that can be specified in MXML. If you put several controls
into a VBox, those are its content children. Non-content children
are the other ones that you get automatically, such as a
background/border, scrollbars, the titlebar of a Panel,
AccordionHeaders, etc.

Most application developers are uninterested in non-content children,
so Container overrides APIs such as numChildren and getChildAt()
to deal only with content children. For example, Container, keeps
its own _numChildren counter.

Container assumes that content children are contiguous, and that
non-content children come before or after the content children.
In order words, Container partitions DisplayObjectContainer's
index range into three parts:

A B C D E F G H I
0 1 2 3 4 5 6 7 8 <- index for all children
0 1 2 3 <- index for content children

The content partition contains the content children D E F G.
The pre-content partition contains the non-content children
A B C that always stay before the content children.
The post-content partition contains the non-content children
H I that always stay after the content children.

Container maintains two state variables, _firstChildIndex
and _numChildren, which keep track of the partitioning.
In this example, _firstChildIndex would be 3 and _numChildren
would be 4.

Thursday, May 7, 2009

Flex Layout Techniques - Part I

From now on I am going add some Flex Layout techniques, with code samples.

1) If you have HBox of some width and wanted to align two controls at each end.

<mx:HBox width="500">
<mx:Button label="Left Button"/>
<mx:Spacer width="100%"/>
<mx:Button label="Right Button"/>
</mx:HBox>


This will align the first button to the left and the second button to the right. There's nothing special about the Spacer, it just extends the UIComponent. It's just a coding trick.

2) If you have Canvas of width and height, how would you align a control to the bottom-right corner. Ofcourse, you can do so by setting the x and y values, which is not the best practice.
If the canvas width and height is dynamic, the x and y values could fail.


<mx:Canvas width="500" height="800">
<mx:Image source="someImage.jpg" width="100" height="100" bottom="10" right="10"/>
</mx:Canvas>

The Image is now set to the bottom-right corner with a padding of 10px on it's sides.
That's simple.. innne...

Example of extending UIComponent

/* A simple example of creating a component by extending the UIComponent.
Creates an icon and label aligned vertically.
Usage of : Style Metadata tag, overriding createChildren(), styleChanged(), measure(), updateDisplayList()
*/


package com.kiran.flex.samples
{

import flash.events.Event;
import flash.geom.Matrix;

import mx.controls.Image;
import mx.controls.Label;
import mx.core.UIComponent;


/**
* Border color of background for the icon.
*
* @default 0xFF0000
*/
[Style(name="iconBackgroundColor", type="uint", format="Color")]

[Style(name = "iconBackgroundThickness", type = "Number", format = "Length", inherit = "no")]

public class CustomComponent extends UIComponent
{


private var _icon : Image;
private var _label : Label;

private var _labelPaddingTop : Number;
private var _iconBackgroundColor : uint = 0x000000;
private var _iconBackgroundThickness : Number = 1;

private var _layuotInitialized : Boolean;
public function MainNavItem()
{
super();
labelPaddingTop = 5;
_icon = new Image();
_label = new Label();

_label.styleName = "navButtonTextStyle";
styleName = "mainNavIconStyle";

_icon.addEventListener(Event.INIT, onIconLoaded );

}

override protected function createChildren():void
{
super.createChildren();

addChild( _icon );
addChild( _label );

}


public function onIconLoaded( p_evt : Event = null ):void
{

layoutLabel();
invalidateDisplayList();
}


public function set icon(p_value:Object):void
{
if( p_value is Class )
{
_icon.source = new p_value();
onIconLoaded();
}
else if( p_value is String )
{
_icon.source = p_value;

}

invalidateDisplayList();

}

public function get text():String
{
return _label.text;
}

public function set text(p_value:String):void
{
_label.text = p_value;
name = p_value;
invalidateSize();
invalidateDisplayList();
}

public function get labelPaddingTop():Number
{
return _labelPaddingTop;
}

public function set labelPaddingTop(p_value:Number):void
{
_labelPaddingTop = p_value;
}


public function get idx():Number
{
return _idx;
}

public function set idx(p_value:Number):void
{
_idx = p_value;
}


private function layoutLabel() : void
{
if( !_layuotInitialized )
{

_label.x = width/2 - _label.textWidth / 2;
_label.y = _icon.contentHeight + labelPaddingTop + _icon.y;
}

}

override public function styleChanged(styleProp:String):void
{
super.styleChanged(styleProp);
if(getStyle("iconBackgroundColor") )
{
_iconBackgroundColor = getStyle("iconBackgroundColor") as uint;
}

if(getStyle("iconBackgroundThickness") )
{
_iconBackgroundThickness = getStyle("iconBackgroundThickness") as Number;
}

invalidateDisplayList();
}

override protected function measure():void
{
super.measure();

if( percentWidth )
{
measuredWidth = percentWidth;
}

if( percentHeight )
{
measuredHeight = percentHeight;
}

if( width )
{
measuredWidth = width;
}

if( height )
{
measuredHeight = height;
}

if( !measuredWidth )
{
measuredWidth = _icon.contentWidth;
}

if( !measuredHeight )
{
measuredHeight = _icon.contentHeight + labelPaddingTop + _label.getExplicitOrMeasuredHeight();
}


}
override protected function commitProperties():void
{
super.commitProperties();
}
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
super.updateDisplayList(unscaledWidth, unscaledHeight );
for(var i:Number = 0; i < numChildren; i++)
{
var uic : UIComponent = getChildAt( i ) as UIComponent;
uic.setActualSize(uic.getExplicitOrMeasuredWidth(), uic.getExplicitOrMeasuredHeight() );
}
//draw background circle for the icon, looks like a border
_icon.graphics.clear();
_icon.graphics.beginFill( _iconBackgroundColor );
_icon.graphics.drawCircle( _icon.contentWidth / 2, _icon.contentHeight /2, _icon.contentWidth/2 + _iconBackgroundThickness);
_icon.graphics.endFill();


layoutLabel();
_layuotInitialized = true;


}

}
}

Saturday, May 2, 2009

Extend UIComponent

Will give a brief about how to create a custom component extending UIComponent..

UIComponent
1)base class for all components in Flex
2)Can wrap Sprite and Movieclip
3) When extending a UIComponent ensure to override updateDisplayList() and set the width and
height of each component, else nothing is displayed on stage.

In my next post, will give a detailed example about creating a UIComponent.

Tuesday, March 31, 2009

Transformation Matrix

Came across changing registration point of a flex component from (0,0) to (x,y)..
DisplayObject class has a property 'transform' which contains object of Matrix.

var do : DisplayObject = new DisplayObject();
var matrix : Matrix = new Matrix();
matrix.tx = x;
matrix.ty = y;

do.transform.matrix = matrix;

That's it..

Monday, January 12, 2009

Flex Date class

I found a bug in Date class of AS 3.0.

Its assumed that always date object is an idle solution for few timer based events.
But, the date object after continuous access over a period of 2 seconds will not show any
difference in the output.

Try this...

var d0:Number = (new Date() ).getTime();
var d1:Number = (new Date() ).getTime();
// iterate this.. you will get same values for both d0 and d1
trace(d0 +" - " + d1);