3.1 The Image Field and NumericStepper field
For the others custom fields we need to proceed in a similar way (create an empty movieclip and associate to it a class file).
For the second custom field
column.cellRenderer = "imageCellRender" // [image] cell renderer
the one containing image do the follow steps:- create a new Symbol in library: imageCellRender, with linkage name of imageCellRender and associated AS2 class: imageCellRender
- in this symbol just create a new empty movieclip (i will use this to load the image into): "img"
the AS2 class associated with is:
import mx.core.UIComponent;
class imageCellRender extends UIComponent {
var img:MovieClip;
var url:String;
var listOwner:MovieClip;
// the reference we receive to the list
var getCellIndex:Function;
// the function we receive from the list
var getDataLabel:Function;
// the function we receive from the list
function imageCellRender() {
}
function createChildren(Void):Void {
size();
}
function setValue(str:String, item:Object, sel:Boolean):Void {
img._visible = (item[getDataLabel()] != undefined);
//We move the head to the label matching
//current cell value
if(item[getDataLabel()] != this.url){
img.loadMovie(item[getDataLabel()]);
this.onEnterFrame = function(){
if(img.getBytesLoaded() >= img.getBytesTotal() && img.getBytesTotal() > 4 && img._width > 4){
this.url = item[getDataLabel()]
delete this.onEnterFrame;
}
}
}
}
function size(Void) : Void
{
img._y = (img._height/2) - 2
}
}
the function automatically invoked from the datagrid is setValue and here we need simply to load the image into the "img" movieclip (item[getDataLabel()] is the string we receive from DataGrid)
- For the numeric stepper field things are different for a little.
This is the command for associate the stepper custom field to the DataGrid column:
column.cellRenderer = "numericRenderer" // cell renderer
- As previous create a new movieclip numericRenderer, linkage: numericRenderer, and AS2 class: NumericRenderer
- Enter in the movieclip just created and drag into the NumericStepper component (name it "stepper")
- in the same frame create a new layer with this code:
stepper.addEventListener("change", this._parent);
stepper.value = this.value
this.watch("value", this.setNewValue)
function setNewValue(id, old_v, new_v){
stepper.value = new_v
}
We just assign a new watcher which everytime the value associate to the field changes, will change the value of the steppers itself.
The Class associated do this:
import mx.core.UIComponent
import mx.controls.NumericStepper
class NumericRenderer extends UIComponent
{
var stepper_cont : MovieClip;
var stepper : MovieClip;
var listOwner : MovieClip; // the reference we receive to the list
var getCellIndex : Function; // the function we receive from the list
var getDataLabel : Function; // the function we receive from the list
function NumericRenderer()
{
}
function createChildren(Void) : Void
{
stepper = stepper_cont.stepper
size();
}
// note that setSize is implemented by UIComponent and calls size(), after setting
// __width and __height
function size(Void) : Void
{
stepper.setSize(80, __height);
stepper._x = (__width-80)/2;
stepper._y = (__height-22)/2;
}
function setValue(str:String, item:Object, sel:Boolean) : Void
{
if(item[getDataLabel()] == undefined){
stepper_cont._visible = false
} else {
stepper_cont._visible = true
}
stepper_cont.value = item[getDataLabel()];
}
function getPreferredHeight(Void) : Number
{
return 22;
}
function getPreferredWidth(Void) : Number
{
return 80;
}
function change()
{
listOwner.dataProvider.editField(getCellIndex().itemIndex, getDataLabel(), stepper_cont.stepper.value);
listOwner.selectedIndex = getCellIndex().itemIndex
listOwner.dispatchEvent({ type:"cellEdit"});
}
}
Here
We have:
- createChildren which is automatically invoked and here just assign the variable stepper to the component we dragged into our movieclip
-
- change which is used by the component stepper once its value change and this propagate the "cellEdit" method of the DataGrid component (this means that you will receive an event "cellEdit" if you add an eventlistener to the datagrid component)
All the API of the cellRenderer can be found here:
http://livedocs.macromedia.com/...file=16_cell4.htm
4. Component Listener
Last step to do is to listen for events of our component (like cellEdit or cellPress).
Click on the DataGrid component you have on the stage and assign this code
on (cellEdit) {
var sel = this.selectedIndex
var data = this.getItemAt(sel)
var price:Number = data.price
var quantity:Number = data.quantity
data.total = price*quantity
data.available = data.quantity > 0
}
on (cellPress) {
var sel = this.selectedIndex
var data = this.getItemAt(sel)
if(data.available == false and data.quantity > 0){
data.quantity = 0
} else if(data.available == true and data.quantity == 0){
data.quantity = 1
}
var price:Number = data.price
var quantity:Number = data.quantity
data.total = price*quantity
}
CellEdit will be invoked when the NumericStepper changed and i use this to change the "total" property of the component each time the stepper change.
CellPress, instead,
start every time you click on the "checkbox" component in the datagrid
5. Conclusion
I think i explained you in a clear way how the DataGrid, and others macromedia component can be easily be customized without changing their library elements (like for example we used to do woth flash mx).
there are many potenetial way to customize a "cellRender", i just wanted to show you some..
Other great examples of cellRenderer can be found here:
http://philflash.inway.fr/example.html
In the same way I hope you see how easy is to use the Serializer class in order to receive complex data type from PHP. In fact we don't need to parse the data or an XML for populating the datagrid with the variables come from PHP.
