Setting BIRT chart series palette dynamically, part 2 – area charts

February 18th, 2010 | Tags: ,

In a previous post we described how to set the series palette dynamically for a pie chart. A slightly different approach is required for area charts.

Let’s recap on the problem at hand: in what is a fairly common scenario, one chooses the palette colours to match with particular category values. For example, in the chart below “High” is represented in green, “Mid” in orange and “Low” in red.

Area chart with three categories

However, if for a particular dataset of the of category values is not present, the palette colours are still used in the same order, meaning the “Mid” area is now shown as red and “High” as orange. This is confusing for the end user.

Area chart with only two categories, palette colours are confusing

Once again we can solve this issue with some scripting of the chart. In this approach, we will override the beforeDrawSeries method to check for category value and set the fill colour based on that:


function beforeDrawSeries( series, isr, icsc )
{
  // get class of the renderer
  var type = isr.getClass().toString();
  // check for area chart renderer
  if( type == "class org.eclipse.birt.chart.render.Area" )
  {
    // get global counter
    // 1* forces conversion to int
    var i = 1 * icsc.getExternalContext().getScriptable().getPersistentGlobalVariable( "seriesCounter" );
    // get category value
    var val = isr.getSeriesRenderingHints().getDataPoints()[0].getSeriesDisplayValue();
    // set fill colour based on category value
    if( val == "1-Low" )
    {
      isr.getSeriesDefinition().getSeriesPalette().getEntries()[i].set( 242, 88, 106, 128 );
    }
    else if( val == "2-Mid" )
    {
      isr.getSeriesDefinition().getSeriesPalette().getEntries()[i].set( 232, 172, 57, 128 );
    }
    else if( val == "3-High" )
    {
      isr.getSeriesDefinition().getSeriesPalette().getEntries()[i].set( 128, 255, 128, 128 );
    }
    // increment global counter
    i = i + 1;
    // "" forces conversion to string
    icsc.getExternalContext().getScriptable().setPersistentGlobalVariable( "seriesCounter", "" + i );
  }
}

You may have noticed that a global variable seriesCounter is used to hold the reference to the current series. This is because the beforeDrawSeries method is called several times, once for each category value present in the data. Another bit of code is therefore required to define the seriesCounter variable in the initialize method of the report:


reportContext.setPersistentGlobalVariable( "seriesCounter", "0" );

One more point to note is that reportContext.setPersistentGlobalVariable only accepts string values, hence the “hack” to convert between a number and a string every time the value is retrieved or stored.

Area chart with only two categories, palette colours dynamically set

  1. Erik
    June 1st, 2010 at 08:07
    Reply | Quote | #1

    Thank you very much, Iäve been looking for this information for, I don’t know how long! You made my day!

  2. June 1st, 2010 at 14:42
    Reply | Quote | #2

    I’m glad you found the post useful Erik. Let me know if you are searching for other BIRT tips, I’d be happy to research it and write another post.

  3. Vincent
    August 31st, 2010 at 09:59
    Reply | Quote | #3

    On another subject
    I’m having issue to dynamically set BarChart palette while using Optionnal Grouping.
    Do you have any Idea?
    isr.getSeriesRenderingHints return null and can’t be used for BarChart.

  4. September 9th, 2010 at 13:16
    Reply | Quote | #4

    Hi Vincent, for bar charts it’s best to use a slightly different approach. I have written up an example, hopefully it will help: http://www.martinhammer.com/blog/?p=575

  5. Vincent
    September 21st, 2010 at 14:24
    Reply | Quote | #5

    Thanks a lot Martin!

  6. Drew
    June 16th, 2011 at 21:03
    Reply | Quote | #6

    Martin, I am also trying to adapt a similar technique to a BarChart.
    I need to store the values/colours from Chart1 in PSGs and change the colours in Chart2 for each value defined in the PSG.
    Also, I have tried to get to your part-3 post on this subject but receive 404s each time.
    Thanks!

    • June 17th, 2011 at 17:26
      Reply | Quote | #7

      Hi Drew, thanks for the heads up about the broken links. It should be fixed now.
      I am not sure if I understand your question correctly, what exactly do you mean by PSGs?