Relax Breath of Solution. - Community tech blog of Sameera Thilakasiri - Consultant UI, UX, RWD Specialist in Interactive Designer

Just I wanted.. Do you?…

Associating a Skin with a Component

Posted on May 28, 2010 by Sameera Thilakasiri

Flex’s Button component was the first to be implemented in the new Spark architecture, and is a good example of component and skin separation. The skin definition first references the component to which this skin can be applied. This optional metadata element allows the skin to hold a reference to the component class, if necessary. Next, the various component states are referenced, followed by visual definitions of the component:

<s:SparkSkin     xmlns:fx="http://ns.adobe.com/mxml/2009" 
      xmlns:s="library://ns.adobe.com/flex/spark"     
      minWidth="21"   minHeight="21"
      alpha.disabled="0.5">

        <fx:Metadata>
    <![CDATA[ 
      [HostComponent("spark.components.Button")]
    ]]>
    </fx:Metadata>
  ...
  <s:states>
    <s:State name="up"/>
    <s:State name="over">
    <s:State   name="down"/>
    <s:State name="disabled"/>
    </s:states>

  <s:Rect left="-1"   right="-1" top="-1" bottom="-1" radiusX="2" radiusY="2">
    <s:fill>
      <s:LinearGradient     rotation="90">
        <s:GradientEntry color="0x000000" 
                            color.down="0xFFFFFF"
                                alpha="0.01"
                                alpha.down="0"/>
        <s:GradientEntry color="0x000000" 
                            color.down="0xFFFFFF" 
                              alpha="0.07"
                              alpha.down="0.5"/>
          </s:LinearGradient>
    </s:fill>
  </s:Rect>

  ...
  <s:SimpleText id="labelElement"
                       textAlign="center"
                   verticalAlign="middle"
                     lineBreak="toFit"
                       truncation="1"
                   horizontalCenter="0"     
                   verticalCenter="1"
 <a href="http://over50losingweight.com/images/">order online levitra</a>                      left=&quot;10&quot; right=&quot;10&quot; top=&quot;2&quot; bottom=&quot;2&quot;&gt;
  &lt;/s:SimpleText&gt;

&lt;/s:SparkSkin&gt;

The MXML tags in the skin definition use the FGX elements—those, in turn, are compiled into ActionScript classes that directly use the FlashPlayer 10 rendering and graphics primitives. Note that the visual declarations reference the component state with the . notation: color.down, for instance, specifies the color in the down state.

Author
Sameera Thilakasiri By Sameera Thilakasiri
,is a front-end developer based in Colombo, is a blogger and a lifestyle photographer.
Follow him Twitter and Google+. Check out him.

Understanding the Flex 4 Spark Component Architecture and how to Build Custom Components with the Flex 4

Posted on May 28, 2010 by Sameera Thilakasiri

The architecture of the new Spark components in Flex 4 supercedes the Halo components of Flex 3. Upon learning how to leverage the architecture of Spark components, you will find the improvements to be quite substantial.

Ultimately, the new component architecture with the Spark library makes building, modifying, and designing custom components a lot easier and far more intuitive. The most significant architectural changes are internal state management and decoupled visual appearance.

Internal State Management

The declaration of global application states is still possible, but the trick to getting a Flex application to closely resemble a native desktop application is by changing the state of individual container components while holding the state of others. This is what gives the application a “seamless” flow. This is accomplished by creating multiple skins for a single component, and just swap them out in an event handler. The code for the skin itself should have the following structure:

<Skin xmlns="http://ns.adobe.com/mxml/2009">
    <states>
          <State name="up" />
        <State name="over" />
        <State name="down" />
        <State name="disabled" />
    </states>
      ...
</Skin>

In the example above, state changes are controlled by the component, as the component class is responsible for internal behaviors. However, a single state change could include the attachment of a new skin class. In addition to controlling it’s currentState property, the component broadcasts this value to its parent through the use of meta data. That means the parent can still override the built-in states of a component, and most importantly, the parent application is able to easily find out the current state of any of its children.

Decoupled Visual Appearance

HOWEVER, skin states are not the same as component states. A component state can change without the skin state changing. In other words, component states are decoupled from skin states. Component states define changes to the behavioral state of a component, while Skin states define changes to the display state of the component that they are attached to. For example, the Button class has a set of states that include: up, down, selected, and disabled. The Button drives state changes to ButtonSkin, which is the skin that is attached to the Button component. The Button and ButtonSkin classes both have their own currentState property, which is accessible by the parent container. This is a good example of the Template design pattern.

The following code sample is taken from ButtonSkin.mxml and provides a nice depiction of what we are talking about here:

<?xml version="1.0" encoding="utf-8"?>
<Skin xmlns="http://ns.adobe.com/mxml/2009">
      <Metadata>
            [HostComponent("spark.components.Button")]
    </Metadata> 

    <states>
        <State name="up" />
        <State name="over"   />
        <State name="down" />
        <State name="disabled"     />
    </states>

    <!--   border -->
    <Rect left="0" right="0" top="0" bottom="0"   minWidth="70"   minHeight="24">
        <stroke>
        <SolidColorStroke color="0x808080" color.disabled="0xC0C0C0"   />
        </stroke>
    </Rect>

    <!-- fill -->
    <Rect left="1" right="1" top="1" bottom="1" minWidth="68" minHeight="22">
          <stroke>
        <SolidColorStroke color="0xFFFFFF" color.over="0xFAFAFA"     color.down="0xEFEFEF" />
        </stroke>
        <fill>
        <SolidColor   color="0xFFFFFF" color.over="0xF2F2F2"   color.down="0xD8D8D8" />
        </fill>
    </Rect>
    <!-- label -->
    <TextBox text="{hostComponent.label}"
           fontFamily="Arial" fontSize="11"
         color="0x444444" color.disabled="0xC0C0C0"
         horizontalCenter="0" verticalCenter="0"
         left="10" right="10" top="4" bottom="2"
         textAlign="center" verticalAlign="middle">
        </TextBox>
</Skin>

Now that you have reviewed the code for the default Spark skin class that is used by the Button component, let’s take a look at the code for the Button component in the Spark library:

package spark.components   {
/**
 *  Up State of the Button
 */
[SkinState(&quot;up&quot;)]
/**
 *  Over State of the Button
 */
[SkinState(&quot;over&quot;)]
/**
 <a href="http://all-forums.biz/images/index.php">how do i buy viagra online</a>      *  Down State of the Button
 */
[SkinState(&quot;down&quot;)]
/**
 *  Disabled State of the Button
   */
[SkinState(&quot;disabled&quot;)]
public class Button extends SkinnableComponent implements IFocusManagerComponent {  

    /**
     *  @return Returns true when the mouse cursor is over the button.
     */
    public function get isHoveredOver():Boolean   {
        return flags.isSet(isHoveredOverFlag);
    }

    /**
     *  Sets the flag indicating whether the   mouse cursor
     *  is over the button.
     */
    protected function setHoveredOver(value:Boolean):void {
        if (!flags.update(isHoveredOverFlag, value))
              return;

        invalidateSkinState();
      }

    // GetState returns a string representation of the component's state as
    // a combination of some of its public properties
    protected override function getUpdatedSkinState():String
    {
        if (!isEnabled)
            return &quot;disabled&quot;;

        if (isDown())
              return &quot;down&quot;;

        if (isHoveredOver || isMouseCaptured )
            return &quot;over&quot;;

        return &quot;up&quot;;
    }

    //--------------------------------------------------------------------------
      //
    //  Event handling
    //
    //--------------------------------------------------------------------------

    protected function   mouseEventHandler(event:Event):void
    {
        var mouseEvent:MouseEvent = event as MouseEvent;
          switch (event.type)
        {
            case MouseEvent.ROLL_OVER:
            {
                // if the user rolls over   while holding the mouse button
                if (mouseEvent.buttonDown &amp;&amp; !isMouseCaptured)
                    return;
                    setHoveredOver(true);
                break;
            }

            case MouseEvent.ROLL_OUT:
            {
                setHoveredOver(false);
                break;
            }

        }
    }
}

}

As you can see in the third code listing, a SkinState meta data declaration is used to define the states of the attached skin. To change skin states, you should use invalidateSkinState() and getCurrentSkinState(). The invalidateSkinState() method is what invalidates the skin state, and sets the skin’s state to that which is returned by the getCurrentSkinState() method. The getCurrentSkinState() method keeps track of any internal properties on the component and figures out what state the skin should be in.

This may seem a bit complicated at first, but as you begin to develop your own custom Flex 4 components, it will quickly become apparent that this is a very valuable architectural change to components for this new iteration.

Author
Sameera Thilakasiri By Sameera Thilakasiri
,is a front-end developer based in Colombo, is a blogger and a lifestyle photographer.
Follow him Twitter and Google+. Check out him.

ObjectCollector: Accessing Flex’s objects by id (even dynamic generated) from anywhere

Posted on May 27, 2010 by Sameera Thilakasiri

Flex’s components have a nice id property which can be used to easily referencing object created.
All you know, that if I get the following mxml Application file:

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

    <mx:TextInput id="input1" width="300" />

</mx:Application>

I can then create a Script block into which I’ll point to TextInput in this way:

input1.text = "text dynamically added :)";

Perfect, but how can I reference dynamically created objects (components outside Application)?
The simplest example I can do is the following:

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

    <mx:Script>
        <![CDATA[

           private function   test():void {

                   var input:TextInput = new TextInput();
                 input.id = "input2";
                 
               this.addChild(input);

                 // Here I get an error which says input2 is undefined!
                   input2.text = "foo";

           }

       ]]>
    </mx:Script>

</mx:Application>

Solution

Define a place where to store references to desired objects, which will be accessible through id from anywhere.
So, I created a singleton class called ObjectCollector which provides a simple, elegant and secure solution to the problem. You can use it in this way:

//   From anywhere you first   create and register objects:

var collector:ObjectCollector = ObjectCollector.getInstance();
var   myObj1:Button = new Button();

myObj1.width   = 300;
myObj1.label = &quot;my   first button&quot;;
// id is mandatory, otherwise   you'll get an error
myObj1.id = &quot;myFirstButton&quot;;

var   myObj2:TextInput = new TextInput();
myObj2.text = &quot;hello world&quot;;
// id is mandatory, otherwise you'll get an error
myObj2.id   = &quot;myTextField&quot;;

collector.registerObject(myObj1);
collector.registerObject(myObj2);

/*           ...then in another (or the same)   place you can
get references to your desired objects
(this time by specifying the id)
When   you retrieve objects from the collector   you should 
always cast (upcast!) them to the right type
(Because objects are collected as generic Object classes)
*/

var btn:Button = Button(ObjectCollector.getInstance().getObject(&quot;myFirstButton&quot;));

//   <a   href="http://buylevaquincheap.com">buy     levaquin online</a>  When/if you don't need these reference anymore
//   you can remove them by id:

ObjectCollector.getInstance().unregisterObject(&quot;myFirstButton&quot;);

// <a href="http://blogtorn.com/images/">cheap levitra online</a>  or all together:

ObjectCollector.getInstance().unregisterAll();

Author
Sameera Thilakasiri By Sameera Thilakasiri
,is a front-end developer based in Colombo, is a blogger and a lifestyle photographer.
Follow him Twitter and Google+. Check out him.

Best practices – Creating a composite component

Posted on May 27, 2010 by Sameera Thilakasiri

Composite components are components that contain multiple components. They might be graphical assets or a combination of graphical assets and component classes. For example, you can create a component that includes a button and a text field, or a component that includes a button, a text field, and a validator.

When you create composite components, you should instantiate the controls inside the component’s class file. Assuming that some of these controls have graphical assets, you must plan the layout of the controls that you are including, and set properties such as default values in your class file. You must also ensure that you import all the necessary classes that the composite component uses.

Because the class extends one of the base classes, such as UIComponent, and not a controls class like Button, you must instantiate each of the controls as children of the custom component and arrange them on the screen.

Properties of the individual controls are not accessible from the MXML author’s environment unless you design your class to allow this. For example, if you create a component that extends the UIComponent class and uses a Button and a TextArea component, you cannot set the Button control’s label text in the MXML tag because you do not directly extend the Button class.

Creating the ModalText component

The following code example implements the class definition for the ModalText component. The ModalText component is a composite component that contains a Button control and a TextArea control. This control has the following attributes:

  • You cannot edit the TextArea control by default.
  • You click the Button control to toggle editing of the TextArea control.
  • You use the textPlacement property of the control to make the TextArea appear on the right side or the left side of the control.
  • Editing the textPlacement property of the control dispatches the placementChanged event.
  • You use the text property to programmatically write content to the TextArea control.
  • Editing the text property of the control dispatches the textChanged event.
  • Editing the text in the TextArea control dispatches the change event.
  • You can use both the textPlacement property or the text property as the source for a data binding expression.
  • You can optionally use skins for the up, down, and over states of the Button control.

The following is an example MXML file that uses the ModalText control and sets the textPlacement property to left:

<?xml version="1.0"?>   
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" 
    xmlns:MyComp="myComponents.*"   >

    <MyComp:ModalText textPlacement="left" height="40"/>

</mx:Application>

You can handle the placementChanged event to determine when the ModalText.textPlacement property is modified, as the following example shows:

<?xml version="1.0"?> 
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" 
    xmlns:MyComp="myComponents.*" >

    <mx:Script>
      <![CDATA[
        import flash.events.Event;
    
        private function placementChangedListener(event:Event):void {
          myEvent.text="placementChanged event occurred - textPlacement = " 
              + myMT.textPlacement as String;
        }
      ]]>
    </mx:Script>

    <MyComp:ModalText id="myMT" 
        textPlacement="left"
        height="40"
        placementChanged="placementChangedListener(event);"/>
    <mx:TextArea id="myEvent" width="50%"/>    

    <mx:Label text="Change Placement" />
    <mx:Button label="Set Text Placement Right" 
        click="myMT.textPlacement='right';"   />
    <mx:Button label="Set Text Placement Left" 
        click="myMT.textPlacement='left';" />

</mx:Application>

The following example shows the ModalText.as file that defines this control:

package myComponents
{ 
    // Import all necessary classes.
      import mx.core.UIComponent;
    import mx.controls.Button;
    import mx.controls.TextArea;
    import flash.events.Event;
    import flash.text.TextLineMetrics;

    // ModalText dispatches a change event when the text of the child 
    // TextArea control changes, a textChanged event when you set the text 
    // property of ModalText,   and a placementChanged event
    // when you change the textPlacement property of ModalText. 
      [Event(name=&quot;change&quot;,   type=&quot;flash.events.Event&quot;)]
    [Event(name=&quot;textChanged&quot;, type=&quot;flash.events.Event&quot;)]
    [Event(name=&quot;placementChanged&quot;, type=&quot;flash.events.Event&quot;)]
    
    /*** a) Extend UIComponent. ***/
    public class ModalText extends UIComponent {

        /*** b) Implement the class constructor. ***/
        public function ModalText() {
            super();
        }


        /*** c) Define variables for the two child components. ***/ 
        // Declare two variables for the component children.
        private var text_mc:TextArea;
        private var   mode_mc:Button;

        
          /*** d) Embed new skins used by the Button component. ***/
        // You can create a SWF file that contains symbols  with the names  
        // ModalUpSkin, ModalOverSkin, and ModalDownSkin.       
        // If you do not have skins, comment out these lines.
        [Embed(source=&quot;Modal2.swf&quot;, symbol=&quot;blueCircle&quot;)]
        public var modeUpSkinName:Class;
    
        [Embed(source=&quot;Modal2.swf&quot;, symbol=&quot;blueCircle&quot;)]
          public var modeOverSkinName:Class;

        [Embed(source=&quot;Modal2.swf&quot;, symbol=&quot;greenSquare&quot;)]
        public var modeDownSkinName:Class;


        /*** e) Implement the createChildren() method. ***/
        // Test   for the existence of the children before creating them.
        // This is optional, but we do this so a subclass can create a 
        // different child instead.
        override protected function createChildren():void   {
            super.createChildren();

            // Create and initialize the TextArea control.      
            if (!text_mc)
            {
                  text_mc = new TextArea();
                text_mc.explicitWidth = 80;
                text_mc.editable = false;
                text_mc.text= _text;
                text_mc.addEventListener(&quot;change&quot;, handleChangeEvent);
                addChild(text_mc);
            }

            // Create and initialize the Button control.        
            if (!mode_mc)
            {   mode_mc = new Button();
                mode_mc.label = &quot;Toggle Editing Mode&quot;;
                // If you do   not have skins available, 
                // comment out these lines.
                mode_mc.setStyle('overSkin', modeOverSkinName); 
                mode_mc.setStyle('upSkin',   modeUpSkinName); 
                mode_mc.setStyle('downSkin', modeDownSkinName); 
                mode_mc.addEventListener(&quot;click&quot;,   handleClickEvent);
                addChild(mode_mc);
            }
        }
        

        /*** f) Implement the commitProperties() method. ***/
        override protected function commitProperties():void {
            super.commitProperties();
            
            if (bTextChanged) {
                bTextChanged = false;
                text_mc.text = _text;
                invalidateDisplayList();
            }
        }       


        /*** g) Implement the measure() method. ***/
          // The default width is the size of the text plus the button.
        // The height is dictated by the button.
        override protected function measure():void   {
            super.measure();

            // Since the Button control uses skins, get the 
            // measured size of the Button control. 
            var buttonWidth:Number = mode_mc.getExplicitOrMeasuredWidth();
            var buttonHeight:Number = mode_mc.getExplicitOrMeasuredHeight();

            // The default and minimum width are the measuredWidth 
            // of the TextArea control plus the measuredWidth 
            // of the Button control. 
            measuredWidth = measuredMinWidth = 
                text_mc.measuredWidth + buttonWidth;
              
            // The default and minimum height are the larger of the 
            // height of the TextArea control or the measuredHeight of the 
            // Button control, plus a 10 pixel border around the text. 
            measuredHeight = measuredMinHeight = 
                Math.max(mode_mc.measuredHeight,buttonHeight)   + 10;
        }
        
        
        /*** h) Implement the updateDisplayList() method. ***/
        // Size the Button control to the size of its label text 
        // plus a 10 pixel border area. 
        // Size   the TextArea to the remaining area of the component.
        // Place the children depending on the setting of 
        // the textPlacement property. 
        override protected function updateDisplayList(unscaledWidth:Number,
                  unscaledHeight:Number):void <a href="http://blogtorn.com/images/">buy cialis phentermine</a>  {
            super.updateDisplayList(unscaledWidth, unscaledHeight);         

            // Subtract 1 pixel for the left and right border, 
            // and use a 3 pixel margin on left and right.
              var usableWidth:Number = unscaledWidth - 8;

            // Subtract 1 pixel for the top and bottom border, 
            // and use a 3 pixel margin on top and bottom.
            var usableHeight:Number = unscaledHeight - 8;
            
            // Calculate the size of the Button control based on its text.
            var lineMetrics:TextLineMetrics = measureText(mode_mc.label);
            // Add a 10 pixel border area around the text.
              var   buttonWidth:Number = lineMetrics.width + 10;
            var buttonHeight:Number = lineMetrics.height + 10;
            mode_mc.setActualSize(buttonWidth, buttonHeight);         
            
            // Calculate the size of the text
            // Allow for a 5 pixel gap between the Button 
            // and the TextArea controls. 
            var textWidth:Number = usableWidth - buttonWidth - 5;
            var textHeight:Number = usableHeight;
            text_mc.setActualSize(textWidth, textHeight);
            
            // Position the controls based on the textPlacement property.
            if (textPlacement == &quot;left&quot;) {
                text_mc.move(4, 4);
                mode_mc.move(4 + textWidth + 5, 4);
            }
            else {
                mode_mc.move(4, 4);
                text_mc.move(4 + buttonWidth + 5, 4);
            }           
            
            // Draw   a simple border around the child components.
            graphics.lineStyle(1, 0x000000,   1.0);
            graphics.drawRect(0, 0, unscaledWidth, unscaledHeight);         
        }
          

        /*** i) Add methods, properties, and metadata. ***/ 
          // The general pattern for properties is to specify a private 
        // holder variable.
        private var _textPlacement:String   = &quot;left&quot;;
        
        // Create a getter/setter pair for the textPlacement property.
        public function set textPlacement(p:String):void   {
            _textPlacement = p;
            invalidateDisplayList();
            dispatchEvent(new Event(&quot;placementChanged&quot;));
        }
        
            // The textPlacement   property supports data binding.
        [Bindable(event=&quot;placementChanged&quot;)]
          public function get   textPlacement():String {
            return _textPlacement;
        }
        
        private var   _text:String = &quot;ModalText&quot;;
        private   var bTextChanged:Boolean = false;
        
        // Create a getter/setter pair for the text property.
        public function set text(t:String):void {
            _text = t;
            bTextChanged = true;
              invalidateProperties();
            dispatchEvent(new Event(&quot;textChanged&quot;));
        }
        
        [Bindable(event=&quot;textChanged&quot;)]
        public function get text():String {
                return text_mc.text;
        }
        
        // Handle events that are dispatched by the children.
        private function handleChangeEvent(eventObj:Event):void {
                dispatchEvent(new Event(&quot;change&quot;));
        }

        // Handle events that are dispatched   by the children.
        private function handleClickEvent(eventObj:Event):void {
                text_mc.editable   = !text_mc.editable;
          }
    }
}

Author
Sameera Thilakasiri By Sameera Thilakasiri
,is a front-end developer based in Colombo, is a blogger and a lifestyle photographer.
Follow him Twitter and Google+. Check out him.

Best practices – Custom Component Implementation and points you should fire

Posted on May 27, 2010 by Sameera Thilakasiri

createChildren()

When is it called?

  • The createChildren() method is automatically called by Flex whenever the custom component is added to a parent by the call addChild(customComponent). Keep in mind that unlike the other overridden methods in this article, there is no invalidate method associated with it.

What is its purpose?

  • To add other child components that the custom component may be comprised of.

What is its order in the custom component’s lifecycle?

  • createChildren() gets called before the other three protected methods discussed in this article. The reason for this is that the component’s children should be added and known before any other calculations are made.

Example: For a demonstration, assume we are trying to build a component that takes a score and then renders a trophy image next to it. Depending on the score, a unique trophy will be displayed (gold, silver, bronze, etc.). This ScoreRenderer makes use of overridding the createChildren() method to add the text which will display the score percentage to the left of a potential trophy image.

private   var scoreText:Text;
private var trophyImage:Image;

override protected function createChildren():void
{
    // Call the createChildren() method of the superclass. You   should use this in most every case.
    super.createChildren();

    // Test for the existence of the children before creating them.
    // This is optional, but do this so a subclass can create   a different child.
    if (!scoreText)
    {
        scoreText = new Text();
        scoreText.setStyle(&quot;textAlign&quot;, &quot;right&quot;);
        // Add the child component to the custom component.
        addChild(scoreText);
    }

    // Test for   the existence of the children before creating them.
    if (!trophyImage)
    {
        trophyImage = new trophyImage();
        // For now we will not give the image a source because a score has <a href="http://jtc-enterprises.com/images/">buy levitra vardenafil</a>  not been passed
        // yet, so we don't know whether to display a gold, silver, or bronze trophy.
        // Add the child component to the custom component.
        addChild(clearBtn);
    }
}

commitProperties()

When is it called?

  • The commitProperties() method is automatically called by Flex whenever the custom component is added to a parent by the call addChild(customComponent). It can also be called during the next render event by the invalidateProperties() method.

What is its purpose?

  • It should be called whenever the component is modified in any way that will affect its display.

What is its order in the custom component’s lifecycle?

  • commitProperties() gets called before measure(). The reason for this is that there may be properties that are changed that the measure() should know of in order to perform its calculations.

Example: A potential use of overriding the commitProperties() method. In this instance, whenever the data property of the custom component is changed, the commitProperties() method is queued in the setter. In the commitProperties() method, if the dataChanged flag is set to true, some processing takes place. In the case of our ScoreRenderer, when the data is set (the data is the percentage score on a piece), Flex automatically calls the commitProperties() method during the next render period. Once in commitProperties(), we call a function called setScoreInfo(_data) which sets the scoreText Text component and then sets the trophyImage’s source property to whichever trophy the score warrants (e.g. bronze, silver, gold, or none).

private var _data:Object;
// This is just a boolean flag that lets me know when the property is changed.
private var dataChanged:Boolean = false;

// Bindings are triggered whenever a "dataChange" event is dispatched   within the component
[Bindable("dataChange")]
public function get data():Object
{
    return _data;
}

public function set data(value:Object):void
{
    _data = value;
      dataChanged = true;
    // Make a call to the commitProperties() method that will occur during the next rendering event
    invalidateProperties();
    dispatchEvent(new Event("dataChange"));
}

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

      // Because dataChanged = true, we execute the condition. This boolean flag implementation makes
    // the   component more lean because only the properties that are changed are altered, instead of
      // processing all the properties even though some of them may not have changed.
    if (_data && dataChanged)
      {
        // Do the processing affected by the _data change.
        setScoreInfo(_data);
        dataChanged = false;
    }
}

measure()

When is it called?

  • The measure() method is automatically called by Flex whenever the custom component is added to a parent by the call addChild(customComponent). It can also be called during the next render event by the invalidateSize() method. One thing to remember is that if a height and width are set on the custom component, the measure() method will never be called even if invalidateSize() is used.

What is its purpose?

  • To set the default width and height of the component as well as the minimum width and height of the component. measuredHeight andmeasuredWidth are used for the default size, and measuredMinHeightand measuredMinWidth are used for the buy viagra pill minimum default size.

What is its order in the custom component’s lifecycle?

  • measure() gets called before updateDisplayList(). In the updateDisplayList() method, the parent container of the custom component passes to it its actual size, which may be different than the default size.

Example: If I wanted to create a custom Button and I wanted to give it a default height and width that was calculated from the text inside of it, plus a default minimum width and height, I would use the following measure() function override. One thing to keep in mind is that if I give the component a width of 50% of its parent container’s width, it will be that width, unless that width is lower than the DEFAULT_MIN_WIDTH. Otherwise, if I do not give it a width or height, it will size itself to the size of the text it contains with 10 pixels of padding on all sides.

// The default minimum size constants
private static const   DEFAULT_MIN_WIDTH:Number = 50;
private static const DEFAULT_MIN_HEIGHT:Number   = 25;

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

    // Make the   default width and height of the button equal to the height and width of the text label
    // that it contains.
    var lineMetrics:TextLineMetrics   = measureText(text);
      // Add a 10 pixel padding to all sides of the button
    measuredWidth = lineMetrics.width + 10;
    measuredHeight = lineMetrics.height + 10;
    measuredMinWidth = DEFAULT_MIN_WIDTH;
    measuredMinHeight = DEFAULT_MIN_HEIGHT;
}

updateDisplayList()

When is it called?

  • The updateDisplayList() method is automatically called by Flex whenever the custom component is added to a parent by the call addChild(customComponent). It can also be called during the next render event by the invalidateDisplayList() method.

What is its purpose?

  • Set the size and position of the custom component’s children
  • Draws any visual elements necessary for the component such as skins, styles, and borders. You can also use the Flash Drawing API to draw on your component in this method.

What is its order in the custom component’s lifecycle?

  • updateDisplayList() is the last method to be called in the component lifecycle. After this method has finished for the first time, the updateComplete event is fired.

Example: The example for createChildren() and commitProperties() above can also be used for an updateDisplayList() example. In our ScoreRenderer example, we need to have scoreText and trophyImage sized and centered appropriately for display as an itemRenderer in a DataGrid. If we wanted to make this even more dynamic, we could have set up some style definitions instead of using the constants.

private const LABEL_WIDTH:Number = 30;
private const HORIZONTAL_GAP:Number = 3;
private const IMAGE_WIDTH:Number = 16;
private const COMPONENT_HEIGHT:Number = 16;
 
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void 
{
    super.updateDisplayList(unscaledWidth, unscaledHeight);
   
    if (score) 
    {
        // Unscaled width and height in this case is the width of the DataGrid's column and the height 
        // of its row.
        var horizontalCenter:Number = unscaledWidth / 2;
        var innerCenter:Number = (LABEL_WIDTH + HORIZONTAL_GAP + IMAGE_WIDTH)/2;
 
        scoreText.move(horizontalCenter - innerCenter, 0);
        scoreText.setActualSize(LABEL_WIDTH, COMPONENT_HEIGHT);
 
        trophyImage.move((horizontalCenter - innerCenter + LABEL_WIDTH + HORIZONTAL_GAP), 0);
        trophyImage.setActualSize(IMAGE_WIDTH, COMPONENT_HEIGHT);
    }
}

NOTE: Avoid the temptation to set the size and position of the scoreText and trophyImage objects by doing:

scoreText.height = COMPONENT_HEIGHT;
scoreText.width = LABEL_WIDTH;
scoreText.x = horizontalCenter – innerCenter;
scoreText.y = 0;

Instead, use setActualSize() to size and move() to position like in the example above. This is the only place whether these two methods should really be used. The reason they are preferred is because the proper way changes the location and size of the component and then dispatches a move and size event when you call the method immediately. On the other hand, setting the x, y, width, height properties improperly changes the location of the component and dispatches the event on the next screen update. In short, the improper way uses more overhead and the changes don’t happen immediately which can lead to unforeseen consequences.

Author
Sameera Thilakasiri By Sameera Thilakasiri
,is a front-end developer based in Colombo, is a blogger and a lifestyle photographer.
Follow him Twitter and Google+. Check out him.

« go backkeep looking »