VCL for PHP Charting components - Part 6 - Generating the Chart

By: David Intersimone

Abstract: Creating a VCL for PHP Charting component. This article is a reproduction of the blog post by Jose Leon, developer of Delphi for PHP.

VCL for PHP Charting components - Generating the chart

In the last article, we learned how to write a property editor to allow the user edit the Series property visually. On this article we are going to use the contents of that property to generate the chart, instead use dummy data.

Iterating through Series

At the end of the article, you will get the full source code for the generateChart method, now we are going to review it, step by step. Inside generateChart(), there is a main loop, which iterates through the series on the Series property:

//Iterates through all the series

$series = $this->_series;

reset($series);

while(list($key, $serie) = each($series))

{

//This is the main loop

//all the following code, is inside this loop

}

So in $serie, we are going to have all the values the user entered in the property editor.

Allowing user customization

We added an event to each serie, called OnCustomize, to allow the user change any attribute at run-time, so, the first thing we need to do is to execute that event:

if(!(($this->ControlState & csDesigning) == csDesigning))

{

if($serie[ 'OnCustomize' ] != '')

{

//If we are un run-time and there is an OnCustomize event

//call it to allow the user to override the specific series

//parameters

$event = $serie[ 'OnCustomize' ];

$serie = $this->owner->$event($this, $serie);

}

}

First, we check we are not rendering the component inside the designer, as no events can be fired at that time. Later, if there is a value on the OnCustomize attribute for the serie, we get it, and call the method, stored on $event, which must be a method of the current Page, and send on $sender, the chart itself. We also send the $serie parameter with all the attributes as the $params of the event, and we expect to get the new serie attributes as return of the event.

Creating the series

Now we are reading to create the series object, using the Open Flash Chart PHP API:

//Get parameters to use

$width = $serie[ 'Width' ];

$startangle = $serie[ 'StartAngle' ];

$animate = $serie[ 'Animate' ];

$color = $serie[ 'Color' ];

$alpha = $serie[ 'Alpha' ];

$keytext = $serie[ 'KeyText' ];

$hint= $serie[ 'Hint' ];

$keysize = $serie[ 'KeySize' ];

$funfactor = $serie[ 'FunFactor' ];

$dotsize = $serie[ 'DotSize' ];

$outlinecolor = $serie[ 'OutlineColor' ];

$halosize = $serie[ 'HaloSize' ];

$onclick = $serie[ 'OnClick' ];

//Depending on the serie type

switch($serie[ 'Type' ])

{

case 'ctLine':

$sobject = new line();

$sobject->set_width((int)$width);

$sobject->set_colour($color);

$sobject->set_key($keytext, $keysize);

if ($onclick!='') $sobject->set_on_click($onclick);

break;

case 'ctLineDot':

$sobject = new line_dot();

$sobject->set_halo_size((int)$halosize);

$sobject->set_width((int)$width);

$sobject->set_dot_size((int)$dotsize);

$sobject->set_colour($color);

$sobject->set_key($keytext, $keysize);

if ($onclick!='') $sobject->set_on_click($onclick);

break;

case 'ctLineHollow':

$sobject = new line_hollow();

$sobject->set_halo_size((int)$halosize);

$sobject->set_width((int)$width);

$sobject->set_dot_size((int)$dotsize);

$sobject->set_colour($color);

$sobject->set_key($keytext, $keysize);

if ($onclick!='') $sobject->set_on_click($onclick);

break;

case 'ctBar':

$sobject = new bar();

$sobject->set_alpha($alpha);

$sobject->set_colour($color);

$sobject->set_key($keytext, $keysize);

break;

case 'ctBarFilled':

$sobject = new bar_filled();

$sobject->set_alpha($alpha);

$sobject->set_colour($color);

$sobject->set_outline_colour($outlinecolor);

$sobject->set_key($keytext, $keysize);

break;

case 'ctBarGlass':

$sobject = new bar_glass();

$sobject->set_alpha($alpha);

$sobject->set_colour($color);

$sobject->set_key($keytext, $keysize);

break;

case 'ctBar3D':

$sobject = new bar_3d();

$sobject->set_alpha($alpha);

$sobject->set_colour($color);

$sobject->set_key($keytext, $keysize);

break;

case 'ctBarSketch':

$sobject = new bar_sketch($color, $outlinecolor, $funfactor);

$sobject->set_alpha($alpha);

$sobject->set_colour($color);

$sobject->set_key($keytext, $keysize);

break;

case 'ctBarHorizontal':

$sobject = new hbar($color);

$sobject->set_colour($color);

$sobject->set_key($keytext, $keysize);

break;

case 'ctBarStacked':

$sobject = new bar_stack();

break;

case 'ctArea':

$sobject = new area_line();

$sobject->set_width((int)$width);

$sobject->set_dot_size((int)$dotsize);

$sobject->set_halo_size((int)$halosize);

$sobject->set_colour($outlinecolor);

$sobject->set_fill_colour($color);

$sobject->set_fill_alpha($alpha);

$sobject->set_key($keytext, $keysize);

break;

case 'ctAreaHollow':

$sobject = new area_hollow();

$sobject->set_width((int)$width);

$sobject->set_dot_size((int)$dotsize);

$sobject->set_halo_size((int)$halosize);

$sobject->set_colour($outlinecolor);

$sobject->set_fill_colour($color);

$sobject->set_fill_alpha($alpha);

$sobject->set_key($keytext, $keysize);

break;

case 'ctPie':

$sobject = new pie();

//On the designer, set animate always to false, as that will

//prevent the designer to draw the chart properly

if(($this->ControlState & csDesigning) == csDesigning) $sobject->set_animate(false);

else

{

if($animate == 'false') $sobject->set_animate(false);

else $sobject->set_animate(true);

}

$sobject->set_start_angle((int)$startangle);

break;

default:

throw new Exception('Graph type ['.$serie[ 'Type' ].'] not supported');

}

This switch is the heart of the generateChart method, as it creates the serie object, depending on the type of serie the user wants to create. And depending on the type of serie, it sets the various attributes.

Note a couple of things

if ($onclick!='') $sobject->set_on_click($onclick);

Some series support javascript clicking events, so if that event has been generated on the property editor, we attach it to the serie, so it will be called.

case 'ctPie':

$sobject = new pie();

//On the designer, set animate always to false, as that will

//prevent the designer to draw the chart properly

if(($this->ControlState & csDesigning) == csDesigning) $sobject->set_animate(false);

else

{

if($animate == 'false') $sobject->set_animate(false);

else $sobject->set_animate(true);

}

$sobject->set_start_angle((int)$startangle);

break;

The Pie chart, supports animation, when it’s shown, the pie performs a small animation with the pieces. As this will cause problems to be rendered on the IDE, if we are in design-time, we always set animate to false on the Pie chart.

The full code

Now, the generateChart method is ready to render the Series property, here is the full code:

function generateChart()

{

//Includes the open flash chart library

use_unit('openchart/php-ofc-library/open-flash-chart.php');

//Creates the title

$title = new title($this->Title);

//Creates the chart

$chart = new open_flash_chart();

$chart->set_title($title);

//Iterates through all the series

$series = $this->_series;

reset($series);

while(list($key, $serie) = each($series))

{

if(!(($this->ControlState & csDesigning) == csDesigning))

{

if($serie[ 'OnCustomize' ] != '')

{

//If we are un run-time and there is an OnCustomize event

//call it to allow the user to override the specific series

//parameters

$event = $serie[ 'OnCustomize' ];

$serie = $this->owner->$event($this, $serie);

}

}

//Get parameters to use

$width = $serie[ 'Width' ];

$startangle = $serie[ 'StartAngle' ];

$animate = $serie[ 'Animate' ];

$color = $serie[ 'Color' ];

$alpha = $serie[ 'Alpha' ];

$keytext = $serie[ 'KeyText' ];

$hint= $serie[ 'Hint' ];

$keysize = $serie[ 'KeySize' ];

$funfactor = $serie[ 'FunFactor' ];

$dotsize = $serie[ 'DotSize' ];

$outlinecolor = $serie[ 'OutlineColor' ];

$halosize = $serie[ 'HaloSize' ];

$onclick = $serie[ 'OnClick' ];

//Depending on the serie type

switch($serie[ 'Type' ])

{

case 'ctLine':

$sobject = new line();

$sobject->set_width((int)$width);

$sobject->set_colour($color);

$sobject->set_key($keytext, $keysize);

if ($onclick!='') $sobject->set_on_click($onclick);

break;

case 'ctLineDot':

$sobject = new line_dot();

$sobject->set_halo_size((int)$halosize);

$sobject->set_width((int)$width);

$sobject->set_dot_size((int)$dotsize);

$sobject->set_colour($color);

$sobject->set_key($keytext, $keysize);

if ($onclick!='') $sobject->set_on_click($onclick);

break;

case 'ctLineHollow':

$sobject = new line_hollow();

$sobject->set_halo_size((int)$halosize);

$sobject->set_width((int)$width);

$sobject->set_dot_size((int)$dotsize);

$sobject->set_colour($color);

$sobject->set_key($keytext, $keysize);

if ($onclick!='') $sobject->set_on_click($onclick);

break;

case 'ctBar':

$sobject = new bar();

$sobject->set_alpha($alpha);

$sobject->set_colour($color);

$sobject->set_key($keytext, $keysize);

break;

case 'ctBarFilled':

$sobject = new bar_filled();

$sobject->set_alpha($alpha);

$sobject->set_colour($color);

$sobject->set_outline_colour($outlinecolor);

$sobject->set_key($keytext, $keysize);

break;

case 'ctBarGlass':

$sobject = new bar_glass();

$sobject->set_alpha($alpha);

$sobject->set_colour($color);

$sobject->set_key($keytext, $keysize);

break;

case 'ctBar3D':

$sobject = new bar_3d();

$sobject->set_alpha($alpha);

$sobject->set_colour($color);

$sobject->set_key($keytext, $keysize);

break;

case 'ctBarSketch':

$sobject = new bar_sketch($color, $outlinecolor, $funfactor);

$sobject->set_alpha($alpha);

$sobject->set_colour($color);

$sobject->set_key($keytext, $keysize);

break;

case 'ctBarHorizontal':

$sobject = new hbar($color);

$sobject->set_colour($color);

$sobject->set_key($keytext, $keysize);

break;

case 'ctBarStacked':

$sobject = new bar_stack();

break;

case 'ctArea':

$sobject = new area_line();

$sobject->set_width((int)$width);

$sobject->set_dot_size((int)$dotsize);

$sobject->set_halo_size((int)$halosize);

$sobject->set_colour($outlinecolor);

$sobject->set_fill_colour($color);

$sobject->set_fill_alpha($alpha);

$sobject->set_key($keytext, $keysize);

break;

case 'ctAreaHollow':

$sobject = new area_hollow();

$sobject->set_width((int)$width);

$sobject->set_dot_size((int)$dotsize);

$sobject->set_halo_size((int)$halosize);

$sobject->set_colour($outlinecolor);

$sobject->set_fill_colour($color);

$sobject->set_fill_alpha($alpha);

$sobject->set_key($keytext, $keysize);

break;

case 'ctPie':

$sobject = new pie();

//On the designer, set animate always to false, as that will

//prevent the designer to draw the chart properly

if(($this->ControlState & csDesigning) == csDesigning) $sobject->set_animate(false);

else

{

if($animate == 'false') $sobject->set_animate(false);

else $sobject->set_animate(true);

}

$sobject->set_start_angle((int)$startangle);

break;

default:

throw new Exception('Graph type ['.$serie[ 'Type' ].'] not supported');

}

$min = 0;

$max = 10;

$values = array();

for($i = 1; $i <= 10; $i++) $values[ ] = rand($min, $max);

$sobject->set_values($values);

//Add the serie to the chart

$chart->add_element($sobject);

}

if($this->_backgroundcolor != "") $chart->set_bg_colour($this->_backgroundcolor);

//Get the json code

$chartoutput = $chart->toPrettyString();

if(($this->ControlState & csDesigning) == csDesigning)

{

//In design time, we need to store that information on a file

//and feed the chart with that file

$url = getScriptFilename();

$dir = dirname($url);

$tempfile = $dir.'\chart.json';

file_put_contents($tempfile, $chartoutput);

}

else

{

//On run time, just dump it to the output

echo $chartoutput;

}

}

Server Response from: ETNASC01