Flex Gantt Charts

31 07 2009

There are a few examples of Gantt charts in Flex out there. And Doug McCune has a pretty good article on the topic.

But none of the existing implementations really met my needs (I’m picky). Most seemed more like bar charts than gantt charts and I wanted something specifically time based. So I spent the afternoon creating my own.

My design goals were to have a component:

  • That could be used stand alone or as and itemRenderer in DataGrid
  • Could be used in an appointment scheduling app, so clicking on an event should fire an event that lets me know exactly what was clicked and clicking on the time line should let me know at exactly what time (on the timeline) the user clicked.
  • Provided the user with feedback about where they were on the timeline. So tick marks and tooltips were essential.
  • Could be used to display ranges from seconds to years.
  • Was configurable and stylable.

So here is what I came up with. I created an actionscript class that extended the UIComponent class and implemented IListItemRenderer and IDataRenderer (so it could be used as an item renderer).

The component creates two layers then. The _bg layer for all of the tick marks and the _fg layer to display all of the events.  Drawing the _fg layer, adding the rectangles for each event and adding tooltips and click event handlers to each was pretty straight forward and you can check it out in the source code. I did want to show what I did when creating the background layer.

private function drawBackground():void
{
  _bg.graphics.clear();
  while(_bg.numChildren > 0) {
    _bg.removeChildAt(0);
  }
  if(_startDt != null && _endDt != null) {
    var range:Number = (_endDt.time - _startDt.time) / 1000;
    var tickSize:Number = calcTickSize(range);
    var tickCnt:int = width / tickSize;
    var dt:Date;
    var tickColor:Number = getStyle('tickColor');
    var tickAlpha:Number = getStyle('tickAlpha');

    _bg.graphics.lineStyle(1, tickColor, tickAlpha);

    var tooltipBox:UIComponent = new UIComponent();
    tooltipBox.graphics.beginFill(0xFFFFFF, 0.0); //clear
    tooltipBox.graphics.drawRect(this.width - (tickSize / 4),0, tickSize / 4, this.height);
    tooltipBox.toolTip = DateUtils.format(_endDt, _endpointFmt);
    tooltipBox.graphics.endFill();
    _bg.addChild(tooltipBox);

    for( var i:int=0; i<tickCnt; i++ ) {
      tooltipBox = new UIComponent();
      tooltipBox.graphics.beginFill(0xFFFFFF, 0.0); //clear
      tooltipBox.graphics.drawRect(tickSize * i - tickSize / 4, 0, tickSize / 2, this.height);
      dt = new Date(_startDt.time + (_secondsPerTick * i * 1000));
      tooltipBox.toolTip = (i==0) ? DateUtils.format(dt, _endpointFmt)
        : DateUtils.format(dt, _tickFmt);
      tooltipBox.graphics.endFill();
    if (i > 0) {
      // draw tick mark
      tooltipBox.graphics.lineStyle(1, tickColor, tickAlpha);
      tooltipBox.graphics.moveTo(tickSize * i, 0);
      tooltipBox.graphics.lineTo(tickSize * i, height);
    }
    _bg.addChild(tooltipBox);
  }
}
}

So lets step through it. The first thing we have to do is clear out anything that is already in the bg layer so we don’t draw over top of it. Next we get the range (in seconds) of our timeline, and call the calcTickSize() function. This just analyzes the range and decides how far apart the tick marks should be and the display format for the tooltip display.

After when know how many tick marks we need, we loop through adding a tick mark surounded by a  transparent box so when the user mouses over a tick mark they can see what time it represents. And a clear box at each end of the chart displays a detailed date/time for that end.


Gantt Charts in Adobe Flex

Gantt Charts in Adobe Flex

Click image to load Flex app.








Follow

Get every new post delivered to your Inbox.