Tuesday, May 29, 2012

Custom Text in DataGridColumn Header ToolTip

DataGridColumn header of Flex DataGrid does not provide toopTip property to show custom text in custom property.

To show your custom text in the tooltip of DataGridColumn Header you need to to create two classes as:
  1. one class extends DataGridColumn say CustomDataGridColumn and
  2. other class extends any class that supports tooltip like Label say CustomHeaderRenderer

//CustomDataGridColumn
import mx.controls.dataGridClasses.DataGridColumn;
public class CustomDataGridColumn extends DataGridColumn{
    private var _toolTip:String;
    
    public function ExcitersDataGridColumn(){
       this.headerRenderer = new CustomHeaderRenderer(this);
    }

    public function set toolTip(value:String):void {
       this._toolTip = value;
    }
    
    public function get toolTip():String{
       return this._toolTip;
    }
}

//CustomHeaderRenderer
import mx.controls.Label;
import mx.core.IFactory;

public class CustomHeaderRenderer extends Label implements IFactory{
   private var column:CustomDataGridColumn;

   public function CustomHeaderRenderer(column:CustomDataGridColumn){
      this.column = column;
   }

   public function newInstance():*{
      return new CustomHeaderRenderer(column);
   }

   public override function set data(value:Object):void {
      super.data = value;
      
      if(value is CustomDataGridColumn) {
         this.toolTip = (value as CustomDataGridColumn).toolTip;
      }
   }
}


now in mxml application file instead of <mx:DataGridColumn.. you should use
<[your package]:CustomDataGridColumn...

Example



<[your package name space]:CustomDataGridColumn dataField="project" toolTip="my custom tool tip text"/>


There it is. Now you can set your own custom tool tip text as shown above.








Java: "==" and "equals"

Though may sound same, "==" and "equals()" are totally different

"==" compares whether the two objects are same instances or not. It will return true if the two objects under comparison refers to the same instance in the JVM.

While the default implementation of "equals()" method which resides in the class Object is implemented such that it checks both the state i.e the contents of the objects under comparison as well as the reference to the object the objects refers to (same as "==" does). So the default implementation of "equals()" method will return true only if the states are same as well as reference to the JVM are also same.

Many examples in the web gives the example to compare two String objects as


  s1 = new String("abc");
  s2 = new String("abc");


  if(s1==s2)
    System.out.printlln("s1==s2 is TRUE");
  else
    System.out.println("s1==s2 is FALSE");
will print False.
while

  if(s1.equals(s2))
    System.out.println("s1.equals(s2) is TRUE");
  else
    System.out.println("s1.equals(s2) is FALSE");
will print true.
IMPORTANT THING TO KEEP IN MIND HERE IS, if s1 and s2 are custom objects instead of String, then s1.equals(s2) will not return true.

For example: I define a custom object as

public class TestObject {

 private String name;
 private int id;
 
 public TestObject(String name, int id) {
  this.name = name;
  this.id = id;
 }
 
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
 public int getId() {
  return id;
 }
 public void setId(int id) {
  this.id = id;
 }
}

Now for

  s1 = new TestObject("xxx", 1);
  s2 = new TestObject("xxx", 1);

s1.equals(s2) will not return True, but False because although s1 and s2 have same contents, they are different objects referring to different references in JVM.

Now to make "equals()" method to return true for matching contents you need to override the "equals()" method.

s1.equals(s2) WORKS FOR STRING, BECAUSE STRING OVERRIDES THE equals() METHOD TO COMPARE THE CONTENTS OF TWO STRINGS. [SEE HERE FOR SOME GOOD EXPLANATIONS]

So to see s1.equals(s2) true for our custom object, our custom class TestObject should also define a method equals as:

  public class TestObject {
    .....
    .....
 
 
    @Override
    public boolean equals(Object obj){
      if (obj == null)
        return false;
      if (obj == this)
        return true;
      if (obj.getClass() != getClass())
        return false;

      TestObject rhs = (TestObject) obj;
        
      if ( rhs.getId() != getId()){
        return false;
      }
      
      if ( rhs.getName() != getName()){
        return false;
      }
      return true;
    }
  }
Now,
System.out.println(obj1 == obj2) will print False
While
System.out.println(obj1.equals(obj2)); will print True
However, when you override equals() method you also need to override hashcode() method. See HERE for details.






Monday, May 30, 2011

The riddle of n = n++ ???

What would be the result of


int n = 0;
for( int m = 0; m < 5; m++){
   n = n++;
   print(n);
}

Well, even i had been confused. Later with lots of discussions, I have concluded that it is compiler dependent.

Lets look at JAVA first.
In java, while executing the statement
n = n++
what actually happens is, an intermediate variableis created. It stores the original value of n. so the sequence is

temp = n;
n++;
n = temp;

Thus in JAVA, the output is
0 0 0 0 0


Now lets look at C and C++.
In these compilers, there is Direct Memory Operations with Pointers without the use of intermediate variables.

So the result in this case is what many people would expect. That is
1 2 3 4 5







Monday, January 3, 2011

Handle Data Sorting in DataGridColumn of Flex DataGrid When Data in embedded object within object

When you put the data in dataGridColumn, by default the sorting is handled by considering the content to be String. So when the content is number, then the sorting is not as expected. In Such a case you need to define your custom sorting function.

public class DataObject{
   private var _objName:String;
   
   public function get objName():String {
      return _objName;
   }

   public function set objName(value:String):void {
      _objName=value;
   }

   private var _property:EmbeddedObject;

   public function property():EmbeddedObject{
      return _property;
   }

   public function set property(value:EmbeddedObject):void {
      _property=value;
   }
}

and EmbeddedObject being defined as

public class EmbeddedObject{
   private var _value:Number;

   public function get value():Number {
      return _value;
   }

   public function set value(value:String):void {
      _value=value;
   }

}

Now in you mxml application file:

private var embeddedobject:String="";
private var value:String="";

private function setTypes(event:DataGridEvent):void {
   var components:Array = event.dataField.split(".");
   embeddedobject= components[0];
   value = components[1];
}

private function customSort(obj1:Object, obj2:Object):int{
   var component1:Number = (obj1[embeddedobject])[value];
   var component2:Number = (obj2[embeddedobject])[value];

   if( component1 <> component
      return -1;
   } else if( component1 == component2 ){
      return 0;
   }

   return 1;
}

<mx:DataGrid headerRelease="setTypes(event)" height="100%" dataProvider="{data}" >
  <mx:DataGridColumn dataField="objName" headerText="objName"/>
  <mx:DataGridColumn dataField="property.value" headerText="embeddedObjName" sortCompareFunction="customSort"/>
/>








Handle Data Display in DataGridColumn of Flex DataGrid When Data in embedded object within object

suppose the data received is var data:ArrayCollection, data being set to the array of object DataObject defined as

  public class DataObject {
    private var _objName : String;
    
    public function get objName() : String {
       return _objName;
    }

    public function set objName(value : String) : void {
      _objName = value;
    }

    private var _property : EmbeddedObject;
    
    public function property() : EmbeddedObject {
      return _property;
    }

    public function set property(value : EmbeddedObject) : void {
      _property = value;
    }

and EmbeddedObject being defined as

  public class EmbeddedObject {
    private var _embeddedObjName : String;

    public function get embeddedObjName() : String { 
      return _embeddedObjName; 
    }
      
    public function set embeddedObjName(value:String) : void {
      _embeddedObjName = value;
    }
}

Now when you want to display the variable from EmbeddedObject you can do following:

  <mx:DataGridColumn dataField="objName" headerText="objName"/>
  <mx:DataGridColumn dataField="property.embeddedObjName" headerText="embeddedObjName"/>