Symmetri Developer Blog

May 22, 2009

Render a bar graph within a Flex (Advanced)DataGrid

Flash/Flex - By Shourov Bhattacharya

A nice visual representation of a variable such as a “percentage growth” is a bar graph that shows the value around a central zero point, with different colour bars for negative and positive growth. To render this in an AdvancedDataGrid, we need to create a custom itemRenderer class that overloads the updateDisplayList method and draws a bar using the UIComponent.graphics object. This will give you a grid which looks something like this:

renderBar

Full source code for the item renderer class below.

package com.symmetri.utils.skins
{
    import flash.display.Graphics;
	
    import mx.controls.advancedDataGridClasses.*;
    import mx.controls.listClasses.*;
    import mx.core.IDataRenderer;
    import mx.core.UIComponent;
    import mx.events.FlexEvent;
    import mx.utils.GraphicsUtil;    
	
    [Event(name=dataChange, type=mx.events.FlexEvent)]
    public class ReportBarItemRenderer extends UIComponent implements IDataRenderer, IDropInListItemRenderer, IListItemRenderer
    {
        private var _data : Object = null;
        private var _listData : BaseListData = null;    
	
        public var BAR_MAX_WIDTH:Number = 17;
        public var BAR_HEIGHT:Number = 13;
        public var BAR_X:Number = 20;
        public var BAR_Y:Number = 1;
	
        public var DATA_MAX_VALUE:Number = 50;
	
        public var COLOR_POSITIVE:Number = 0x0D84A4;
        public var COLOR_NEGATIVE:Number = 0xD00A3D;        
	
        public function ReportBarItemRenderer()
        {
            super();
        }
	
        public function get data():Object
        {
            return _data;
        }
	
        public function set data(value:Object):void
        {
            this._data = value;
            this.invalidateProperties();
	
            dispatchEvent(new FlexEvent(FlexEvent.DATA_CHANGE));
        }        
	
        public function get listData():BaseListData
        {
            return _listData;
        }
	
        public function set listData(value:BaseListData):void
        {
            this._listData = value;
            this.invalidateProperties();
	
            dispatchEvent(new FlexEvent(FlexEvent.DATA_CHANGE));
        }    
	
         override protected function updateDisplayList(w:Number, h:Number):void
         {
             super.updateDisplayList(w, h);
	
             if (_data != null)
             {
                // draw a horizontal bar to represent value of data
                // scaled between -1.0 and +1.0
                var _fieldName:String = AdvancedDataGridListData(listData).dataField;
                var _value:String = String(data[AdvancedDataGridListData(listData).dataField]);                            
	
                if (isNaN(Number(_value)))
                {
                    // do nothing, data value not numeric
                }
                else
                {
                    // draw the bar
                    var _scaledValue:Number = Number(_value)/DATA_MAX_VALUE;
                    var _width:Number = _scaledValue*BAR_MAX_WIDTH; 
	
                    // keep a minimum width of 1 pixel
                    if ((_width > -1) && (_width < 0)) _width = -1;
                    if ((_width < 1) && (_width > 0)) _width = 1;
	
                      graphics.clear();
                    graphics.lineStyle(1, 0xFFFFFF, 0); // no border
	
                    if (_scaledValue < 0)
                    {
                        // draw a negative bar
                        graphics.beginFill(COLOR_NEGATIVE, 1);
                        GraphicsUtil.drawRoundRectComplex(graphics, BAR_X+_width, BAR_Y, -_width, BAR_HEIGHT, 0, 0, 0, 0);
                    }
                    else
                    {
                        // draw a negative bar
                        graphics.beginFill(COLOR_POSITIVE, 1);
                        GraphicsUtil.drawRoundRectComplex(graphics, BAR_X, BAR_Y, _width, BAR_HEIGHT, 0, 0, 0, 0);
	
                    }
                     graphics.endFill();
	
                     // draw a tooltip with the data value
                     this.toolTip = _value.toString();
                }
             }
	
             super.validateNow();
         }
    }
}

Get free blog up and running in minutes with Blogsome
Theme designed by Janis Joseph