Tuesday 31 May 2011

Dynamic Classes in Flex and Actionscript

In flex, you must have created ActionScript classes where properties and methods are declared and defined. Flex also let you add properties and methods at run time when you create an object of the class. This all can be achieved using "dynamic" keyword while creating class.

DynamicClass.as

package {

public dynamic class DynamicClass {

public var name:String;

public function displayName():String {

return name;

}
}
}
  

The above class only has one property "name" and one method "displayName()". The above class has the capability to be set new properties and added functions at run time. For example: In the below mxml, we added new property "place" and one new method "displayPlace()".

Dynamic.mxml

<?xml version="1.0" encoding="utf-8"?>

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"

creationComplete="init()">

<mx:Script>

<![CDATA[

import mx.controls.Alert;

public function init():void {

var dynamicClassObj:DynamicClass = new DynamicClass();

dynamicClassObj.name = "Roseindia";

// Adding property to the object of dynamic class at runtime

dynamicClassObj.place = "New Delhi";

// Adding method to the object of dynamic class at runtime

dynamicClassObj.displayPlace = function():String {

return this.place;

};

Alert.show(dynamicClassObj.displayName()+", "+ dynamicClassObj.displayPlace());

}
]]>

</mx:Script>
</mx:Application>

The output of the above application is as below:

Tuesday 24 May 2011

Observer Design Pattern in Flex


 how Observer Pattern works:
First of all you must create an Interface (IObserver) that has an update method that will be called from Observer manager when a notification will be called:
public interface IObserver {
    function update(_notification:String):void;
}
Then you must have an Observer Manager that manage all objects that implements IObserver interface.
This manager will have 3 public methods: subscribe, unsubscribe and notify.
You call subscribe when you want to add an object that is update from Observer; unsubscribe when you remove an object from a displaylist or if you don’t need to update anymore  and notify when you want to notify something to all subscribed objects:
public class ObserverManager {
private static var instance : ObserverManager;
private var observerData : Array;
public function ObserverManager():void{
observerData = new Array();
}
public static function getInstance() : ObserverManager{
if(instance == null)
instance = new ObserverManager();
return instance;
}
public function subscribe(observer:IObserver):void{
observerData.push(observer);
}
public function unsubscribe(observer : IObserver) : void {
var totObs:int = observerData.length;
for(var i:int = 0; i < totObs; i++){
if(observer === observerData[i]){
observerData.splice(i, 1);
break;
}
}
}
              
       public function notify(_notification:String):void{
var totObs:int = observerData.length;
for(var i:int = 0; i < totObs; i++){
observerData[i].update(_notification);
}
}
}
Ok now you are ready to work with observer, so we create an object that implements IObserver and another one that add on displaylist all IObserver objects and notify to all some notifications:
custom button that implements IObserver interface:
public class ObserverButton extends Button implements IObserver

{

 public static const HIDE_BUTTON:String = "hideBtnEvt";

 public static const SHOW_BUTTON:String = "showBtnEvt";

  

 public function ObserverButton()

 {

  super();   

 }

  

 public function update(_notification:String):void

 { 

  switch(_notification){   

   case HIDE_BUTTON:

    this.alpha = .2;

    break;

    

   case SHOW_BUTTON:

    this.alpha = 1;

    break;

  }   

 }

}

subscribe some custom buttons to observer manager:   

protected var observer:ObserverManager;

protected function init():void{    

 observer = ObserverManager.getInstance();

 for(var i:int = 0; i < 100; i++){   

  var btn:ObserverButton = new ObserverButton();

  btn.label = i.toString()

  addElement(btn);




  if((i & 1) == 0)

   observer.subscribe(btn);

     

  btn.x = Math.random() * 800;

  btn.y = Math.random() * 500 + 70;

     

Run Example  

Monday 23 May 2011

How to use PODS in Flex

<?xml version="1.0" encoding="utf-8"?>
<!--
 The main application file for the Dashboard demo app.
 Loads the layout XML and creates PodLayoutManagers.
-->
<mx:Application
    xmlns:mx="http://www.adobe.com/2006/mxml"
    horizontalAlign="left"
    minWidth="600" minHeight="600"
    width="100%" height="100%"
    backgroundSize="100%"
    backgroundColor="#ffffff"
    paddingLeft="45" paddingRight="45" paddingBottom="35" paddingTop="34"
    applicationComplete="onApplicationComplete()" viewSourceURL="srcview/index.html">
    <mx:Style source="/assets/styles.css" />
    <mx:Script>
        <![CDATA[
            import com.esria.samples.dashboard.events.LayoutChangeEvent;
            import com.esria.samples.dashboard.managers.PodLayoutManager;
            import com.esria.samples.dashboard.managers.StateManager;
            import com.esria.samples.dashboard.view.ChartContent;
            import com.esria.samples.dashboard.view.FormContent;
            import com.esria.samples.dashboard.view.ListContent;
            import com.esria.samples.dashboard.view.PieChartContent;
            import com.esria.samples.dashboard.view.Pod;
            import com.esria.samples.dashboard.view.PodContentBase;
            import mx.containers.Canvas;
            import mx.controls.Alert;
            import mx.events.FlexEvent;
            import mx.events.IndexChangedEvent;
            import mx.events.ItemClickEvent;
            import mx.rpc.events.FaultEvent;
            import mx.rpc.events.ResultEvent;
            import mx.rpc.http.HTTPService;
           
            // Array of PodLayoutManagers
            private var podLayoutManagers:Array = new Array();
           
            // Stores the xml data keyed off of a PodLayoutManager.
            private var podDataDictionary:Dictionary = new Dictionary();
           
            // Stores PodLayoutManagers keyed off of a Pod.
            // Used for podLayoutManager calls after pods have been created for the first time.
            // Also, used for look-ups when saving pod content ViewStack changes.
            private var podHash:Object = new Object();
           
            private function onApplicationComplete():void
            {
                // Load pods.xml, which contains the pod layout.
                var httpService:HTTPService = new HTTPService();
                httpService.url = "data/pods.xml";
                httpService.resultFormat = "e4x";
                httpService.addEventListener(FaultEvent.FAULT, onFaultHttpService);
                httpService.addEventListener(ResultEvent.RESULT, onResultHttpService);
                httpService.send();
            }
           
            private function onFaultHttpService(e:FaultEvent):void
            {
                Alert.show("Unable to load data/pods.xml.");
            }
           
            private function onResultHttpService(e:ResultEvent):void
            {
                var viewXMLList:XMLList = e.result.view;
                var len:Number = viewXMLList.length();
                var containerWindowManagerHash:Object = new Object();
                for (var i:Number = 0; i < len; i++) // Loop through the view nodes.
                {
                    // Create a canvas for each view node.
                    var canvas:Canvas = new Canvas();
                    // PodLayoutManager handles resize and should prevent the need for
                    // scroll bars so turn them off so they aren't visible during resizes.
                    canvas.horizontalScrollPolicy = "off";
                    canvas.verticalScrollPolicy = "off";
                    canvas.label = viewXMLList[i].@label;
                    canvas.percentWidth = 100;
                    canvas.percentHeight = 100;
                    viewStack.addChild(canvas);
                   
                    // Create a manager for each view.
                    var manager:PodLayoutManager = new PodLayoutManager();
                    manager.container = canvas;
                    manager.id = viewXMLList[i].@id;
                    manager.addEventListener(LayoutChangeEvent.UPDATE, StateManager.setPodLayout);
                    // Store the pod xml data. Used when view is first made visible.
                    podDataDictionary[manager] = viewXMLList[i].pod;
                    podLayoutManagers.push(manager);
                }
               
                var index:Number = StateManager.getViewIndex();
                // Make sure the index is not out of range.
                // This can happen if a tab view was saved but then tabs were subsequently removed from the XML.
                index = Math.min(tabBar.numChildren - 1, index);
                onItemClickTabBar(new ItemClickEvent(ItemClickEvent.ITEM_CLICK, false, false, null, index));
                tabBar.selectedIndex = index;
            }
           
            private function onItemClickTabBar(e:ItemClickEvent):void
            {
                var index:Number = e.index;
                StateManager.setViewIndex(index); // Save the view index.
               
                viewStack.selectedIndex = index;
               
                // If data exists then add the pods. After the pods have been added the data is cleared.
                var podLayoutManager:PodLayoutManager = podLayoutManagers[index];
                if (podDataDictionary[podLayoutManager] != null)
                    addPods(podLayoutManagers[index]);
            }
           
            // Adds the pods to a view.
            private function addPods(manager:PodLayoutManager):void
            {
                // Loop through the pod nodes for each view node.
                var podXMLList:XMLList = podDataDictionary[manager];
                var podLen:Number = podXMLList.length();
                var unsavedPodCount:Number = 0;
                for (var j:Number = 0; j < podLen; j++)
                {
                    // Figure out which type of pod content to use.
                    var podContent:PodContentBase = null;
                    if (podXMLList[j].@type == "chart")
                        podContent = new ChartContent();
                    else if (podXMLList[j].@type == "form")
                        podContent = new FormContent();
                    else if (podXMLList[j].@type == "list")
                        podContent = new ListContent();
                    else if (podXMLList[j].@type == "pieChart")
                        podContent = new PieChartContent();
                   
                    if (podContent != null)
                    {
                        var viewId:String = manager.id;
                        var podId:String = podXMLList[j].@id;
                       
                        // Get the saved value for the pod content viewStack.
                        if (StateManager.getPodViewIndex(viewId, podId) != -1)
                            podXMLList[j].@selectedViewIndex = StateManager.getPodViewIndex(viewId, podId);
                       
                        podContent.properties = podXMLList[j];
                        var pod:Pod = new Pod();
                        pod.id = podId;
                        pod.title = podXMLList[j].@title;
                        pod.addChild(podContent);
                        var index:Number;
                       
                        if (StateManager.isPodMinimized(viewId, podId))
                        {
                            index = StateManager.getMinimizedPodIndex(viewId, podId);
                            manager.addMinimizedItemAt(pod, index);
                        }
                        else
                        {
                            index = StateManager.getPodIndex(viewId, podId);
                           
                            // If the index hasn't been saved move the pod to the last position.
                            if (index == -1)
                            {
                                index = podLen + unsavedPodCount;
                                unsavedPodCount += 1;
                            }
                           
                            manager.addItemAt(pod, index, StateManager.isPodMaximized(viewId, podId));
                        }
                       
                        pod.addEventListener(IndexChangedEvent.CHANGE, onChangePodView);
                       
                        podHash[pod] = manager;
                    }
                }
               
                // Delete the saved data.
                delete podDataDictionary[manager];
               
                // Listen for the last pod to complete so the layout from the ContainerWindowManager is done correctly.
                pod.addEventListener(FlexEvent.UPDATE_COMPLETE, onCreationCompletePod);
            }
           
            // Pod has been created so update the respective PodLayoutManager.
            private function onCreationCompletePod(e:FlexEvent):void
            {
                e.currentTarget.removeEventListener(FlexEvent.UPDATE_COMPLETE, onCreationCompletePod);
                var manager:PodLayoutManager = PodLayoutManager(podHash[e.currentTarget]);
                manager.removeNullItems();
                manager.updateLayout(false);
            }
           
            // Saves the pod content ViewStack state.
            private function onChangePodView(e:IndexChangedEvent):void
            {
                var pod:Pod = Pod(e.currentTarget);
                var viewId:String = PodLayoutManager(podHash[pod]).id;
                StateManager.setPodViewIndex(viewId, pod.id, e.newIndex);
            }
        ]]>
    </mx:Script>
    <mx:TabBar
        id="tabBar"
        itemClick="onItemClickTabBar(event)"
        height="35"
        dataProvider="viewStack" />
    <mx:ViewStack
        id="viewStack"
        paddingTop="15"
        width="100%" height="100%" />
</mx:Application>