Unfortunately the Steems supplied source code still has bugs. In this case I have created a small test harness which is operative here
http://www.softwaremage.co.nz/charttest/charttest.php
and the source code is downloadable here so that you can use it to test your fixes.
http://www.softwaremage.co.nz/files/ste ... t_test.zip
It took a long time to understand why adding a second bar to a series collection failed becuase it does not, at least in Delphi for PHP, generate an exception. But the bug seems to be buried in a low level graphic routine:
Chartbrush::setColor and also Chartbrush::setForegroundColor
public function setColor($value) {
$this->color = $this->setColorProperty($this->color, $value);
}
setColorProperty is a method of the ancestor class and presumably that is what you want to call.
If you take a look at the demonstration URL I have been able to implement the multibar chart as in the Teechart demo using fillSampleValues which is all well and good.
However, assuming my code is correct it does not seem possible to programmatically add series when other methods are used to populate the chart.
The second chart involves the rendering of a single series barchart. In this case the chart renders the Series Labels even if we call the clear() method to get rid of them. Your suggestion of a couple of days ago of using setVisible(False) does not work either because that method is not implemented on Series Labels. Note too that the series label text is in fact appearing on the Axis labels. Somewhere in the many wrappers for inserting chart values these values must be getting reversed somewhere.
Also the left axis is defective in that the numbering sequence doesnt relate to any other chart artifact.
Because we want to review this product over the weekend and post it for the benefit of the Delphi for PHP community we will be relying upon the version that you supply after fixing this further bug.
But I would appreciate it if you could also use the test harness to test the chart making functionality is working or provide a revised test harness which works with your code to deliver what we want.
Cheers,
Steve Cooney.
Further problems with Teechart for PHP source code
Hi Steve,
To change the axis label style the following code could be used :
The same way should be used to change the Legend Text style.
The Clear() method can be used for axis labels items, in the case you want to use custom axis labels instead of automatic, or just to add extra labels, similar code to the following will do it :
Axis minimum increment can be also modified to desired value by using :
I've also added the support for bold font (a default bold font is used if bold is set to true), but you can always set a specific font (bold or not) by using :
I've sent directly to your mail the sample you sent to me with few modifications.
I'm not sure what you mean here, how can I reproduce the problem here ?It took a long time to understand why adding a second bar to a series collection failed becuase it does not, at least in Delphi for PHP, generate an exception. But the bug seems to be buried in a low level graphic routine:
Chartbrush::setColor and also Chartbrush::setForegroundColor
public function setColor($value) {
$this->color = $this->setColorProperty($this->color, $value);
}
setColorProperty is a method of the ancestor class and presumably that is what you want to call.
If you take a look at the demonstration URL I have been able to implement the multibar chart as in the Teechart demo using fillSampleValues which is all well and good.
However, assuming my code is correct it does not seem possible to programmatically add series when other methods are used to populate the chart.
Maybe I misunderstood your problem. In the case you want to hide the Series Marks you should use the SerVisible method which exist into the TeeShape.php unit (which is the ancestor of SeriesMarks.php). The code to hide would be :The second chart involves the rendering of a single series barchart. In this case the chart renders the Series Labels even if we call the clear() method to get rid of them. Your suggestion of a couple of days ago of using setVisible(False) does not work either because that method is not implemented on Series Labels.
Code: Select all
// Clear out any Marks
$barseries->getMarks()->setVisible(false);[/
Yes, by default, if Series Marks are assigned into the Add method these are used for the labels of the mandatory Axis.Note too that the series label text is in fact appearing on the Axis labels. Somewhere in the many wrappers for inserting chart values these values must be getting reversed somewhere.
To change the axis label style the following code could be used :
Code: Select all
// by default AxisLabelStyle::$AUTO
$teechart->getAxes()->getBottom()->getLabels()->setStyle(AxisLabelStyle::$VALUE);
The Clear() method can be used for axis labels items, in the case you want to use custom axis labels instead of automatic, or just to add extra labels, similar code to the following will do it :
Code: Select all
// To draw custom labels on the axis :
$teechart->getChart()->getAxes()->getBottom()->getLabels()->setStyle(AxisLabelStyle::$TEXT);
$teechart->getChart()->getAxes()->getBottom()->getLabels()->getItems()->clear();
$teechart->getChart()->getAxes()->getBottom()->getLabels()->getItems()->add(0,"mylabel");
Yes, the problem was that decimal numbers was not well displayed, now it has been fixed.Also the left axis is defective in that the numbering sequence doesnt relate to any other chart artifact.
Axis minimum increment can be also modified to desired value by using :
Code: Select all
$teechart->getAxes()->getLeft()->setIncrement(0.2);
Sure. I've been doing some tests with your demo and the latest sources I've just posted on our web site and all seems to work fine. Could you please check if it works fine for you?But I would appreciate it if you could also use the test harness to test the chart making functionality is working or provide a revised test harness which works with your code to deliver what we want.
I've also added the support for bold font (a default bold font is used if bold is set to true), but you can always set a specific font (bold or not) by using :
Code: Select all
$teechart->getFont()->setName($baseDir . "fonts/DejaVuSansCondensed.ttf");
Pep Jorge
http://support.steema.com
http://support.steema.com
Thanks for your reply and the files sent separately. Unfortunately the latest version of the source code is still unable to create multi series charts. Indeed in the sample charts you sent there was no actual example of a successfully generated chart using multiple bar charts so we wonder if you were able to succeed yourself.
However I have persevered debugging your source code and now have it working for the simple charts I currently require. In order to get to this point I have had to make further changes to the source code.
In the Series collection there is a bug which appears to create a case of infinite recursion, which was manifested by an an inability to add multiple series and execution timeouts irrespective of how long the code ran for.
In the series collection class there is a method which gets called repeatedly when a series is added.
public function clear($dispose=true) {
while (sizeof($this) > 0) {
$tmp = $this->getSeries(0);
$this->remove($tmp);
// $tmp->onDisposing();
// if ($dispose) {
// $tmp->dispose();
// }
}
I have had to moddify this so that it iterates through all members of the series collection rather than the zeroth member.
public function clear($dispose=true) {
$seriescount = sizeof($this);
for ($i=0;$i<$seriescount;$i++)
{
$tmp = $this->getSeries($i);
$this->remove($tmp);
}
}
This now allows the method to proceed.
In AxisDraw we had to add a check for a variable being set
private function calcFirstLastAllSeries($rect) {
$tmp = new IntRange(intval('1000000000000'), -1); // MAX_VALUE
for ( $t = 0; $t < sizeof($this->axis->iSeriesList); $t++) {
$s = $this->axis->iSeriesList->getSeries($t);
$s->calcFirstLastVisibleIndex();
if (($s->getFirstVisible() < $tmp->first) &&
($s->getFirstVisible() != -1)) {
$tmp->first = $s->getFirstVisible();
}
if ($s->getLastVisible() > $tmp->last) {
$tmp->last = $s->getLastVisible();
}
}
return $tmp;
}
i.e
private function calcFirstLastAllSeries($rect) {
$tmp = new IntRange(intval('1000000000000'), -1); // MAX_VALUE
for ( $t = 0; $t < sizeof($this->axis->iSeriesList); $t++) {
$s = $this->axis->iSeriesList->getSeries($t);
//
if (isset($s))
{
$s->calcFirstLastVisibleIndex();
if (($s->getFirstVisible() < $tmp->first) &&
($s->getFirstVisible() != -1)) {
$tmp->first = $s->getFirstVisible();
}
if ($s->getLastVisible() > $tmp->last) {
$tmp->last = $s->getLastVisible();
}
}
}
return $tmp;
}
Otherwise PHP raises an error
php[5772]
PHP Fatal error: Call to a member function calcFirstLastVisibleIndex() on a non-object in C:\Program Files\CodeGear\Delphi for PHP\2.0\vcl\teechart\axis\AxisDraw.php on line 387
Then we had to modify AxisLabelsItems:;repaint and apply a similar check:
public function repaint()
{
if (isset($this->iAxisLabelsItems->iAxis->chart))
{
$this->iAxisLabelsItems->iAxis->chart->invalidate();
}
}
to deal with another PHP error:
php[7508]
PHP Fatal error: Call to a member function invalidate() on a non-object in C:\Program Files\CodeGear\Delphi for PHP\2.0\vcl\teechart\axis\AxisLabelItem.php on line 47
Finally I had to modify AxisLabelItems::clear
public function clear() {
// TODO remove parent::clear();
unset($this);
$this->iAxis->chart->invalidate();
}
to remove the call to invalidate after $this has been destroyed in the prior line of code. Otherwise again PHP complains and obviously aborts processing.
That removed we have been able to, finally, make the test harness work.
However I have persevered debugging your source code and now have it working for the simple charts I currently require. In order to get to this point I have had to make further changes to the source code.
In the Series collection there is a bug which appears to create a case of infinite recursion, which was manifested by an an inability to add multiple series and execution timeouts irrespective of how long the code ran for.
In the series collection class there is a method which gets called repeatedly when a series is added.
public function clear($dispose=true) {
while (sizeof($this) > 0) {
$tmp = $this->getSeries(0);
$this->remove($tmp);
// $tmp->onDisposing();
// if ($dispose) {
// $tmp->dispose();
// }
}
I have had to moddify this so that it iterates through all members of the series collection rather than the zeroth member.
public function clear($dispose=true) {
$seriescount = sizeof($this);
for ($i=0;$i<$seriescount;$i++)
{
$tmp = $this->getSeries($i);
$this->remove($tmp);
}
}
This now allows the method to proceed.
In AxisDraw we had to add a check for a variable being set
private function calcFirstLastAllSeries($rect) {
$tmp = new IntRange(intval('1000000000000'), -1); // MAX_VALUE
for ( $t = 0; $t < sizeof($this->axis->iSeriesList); $t++) {
$s = $this->axis->iSeriesList->getSeries($t);
$s->calcFirstLastVisibleIndex();
if (($s->getFirstVisible() < $tmp->first) &&
($s->getFirstVisible() != -1)) {
$tmp->first = $s->getFirstVisible();
}
if ($s->getLastVisible() > $tmp->last) {
$tmp->last = $s->getLastVisible();
}
}
return $tmp;
}
i.e
private function calcFirstLastAllSeries($rect) {
$tmp = new IntRange(intval('1000000000000'), -1); // MAX_VALUE
for ( $t = 0; $t < sizeof($this->axis->iSeriesList); $t++) {
$s = $this->axis->iSeriesList->getSeries($t);
//
if (isset($s))
{
$s->calcFirstLastVisibleIndex();
if (($s->getFirstVisible() < $tmp->first) &&
($s->getFirstVisible() != -1)) {
$tmp->first = $s->getFirstVisible();
}
if ($s->getLastVisible() > $tmp->last) {
$tmp->last = $s->getLastVisible();
}
}
}
return $tmp;
}
Otherwise PHP raises an error
php[5772]
PHP Fatal error: Call to a member function calcFirstLastVisibleIndex() on a non-object in C:\Program Files\CodeGear\Delphi for PHP\2.0\vcl\teechart\axis\AxisDraw.php on line 387
Then we had to modify AxisLabelsItems:;repaint and apply a similar check:
public function repaint()
{
if (isset($this->iAxisLabelsItems->iAxis->chart))
{
$this->iAxisLabelsItems->iAxis->chart->invalidate();
}
}
to deal with another PHP error:
php[7508]
PHP Fatal error: Call to a member function invalidate() on a non-object in C:\Program Files\CodeGear\Delphi for PHP\2.0\vcl\teechart\axis\AxisLabelItem.php on line 47
Finally I had to modify AxisLabelItems::clear
public function clear() {
// TODO remove parent::clear();
unset($this);
$this->iAxis->chart->invalidate();
}
to remove the call to invalidate after $this has been destroyed in the prior line of code. Otherwise again PHP complains and obviously aborts processing.
That removed we have been able to, finally, make the test harness work.
Hi Steve,
first of all, thanks for all of your suggestions and advises.
and worked fine leaving the method as is :
I've updated the sources on our web site, in case you want to download the latest version.
first of all, thanks for all of your suggestions and advises.
Yes, you're correct. Finally I've modified the code you sent to me due to other problems. Here the latest version :In the Series collection there is a bug which appears to create a case of infinite recursion, which was manifested by an an inability to add multiple series and execution timeouts irrespective of how long the code ran for.
In the series collection class there is a method which gets called repeatedly when a series is added.
Code: Select all
public function remove($s) {
$i = $this->indexOf($s);
if ($i > -1) {
parent::offsetUnset($i);
$tmpArray=Array();
foreach($this as $item)
{
$tmpArray[]=$item;
}
$this->clear();
for ($i=0;$i<sizeof($tmpArray);$i++)
{
$this[$i]=$tmpArray[$i];
}
}
}
public function clear($dispose=true) {
foreach($this as $key=>$item)
{
parent::offsetUnset($key);
}
}
Ok, I've added this check into the sources.In AxisDraw we had to add a check for a variable being set
i.e
private function calcFirstLastAllSeries($rect) {
$tmp = new IntRange(intval('1000000000000'), -1); // MAX_VALUE
for ( $t = 0; $t < sizeof($this->axis->iSeriesList); $t++) {
$s = $this->axis->iSeriesList->getSeries($t);
//
if (isset($s))
{
$s->calcFirstLastVisibleIndex();
if (($s->getFirstVisible() < $tmp->first) &&
($s->getFirstVisible() != -1)) {
$tmp->first = $s->getFirstVisible();
}
if ($s->getLastVisible() > $tmp->last) {
$tmp->last = $s->getLastVisible();
}
}
}
return $tmp;
}
I've added this check into the sources.php[5772]
PHP Fatal error: Call to a member function calcFirstLastVisibleIndex() on a non-object in C:\Program Files\CodeGear\Delphi for PHP\2.0\vcl\teechart\axis\AxisDraw.php on line 387
Then we had to modify AxisLabelsItems:;repaint and apply a similar check:
public function repaint()
{
if (isset($this->iAxisLabelsItems->iAxis->chart))
{
$this->iAxisLabelsItems->iAxis->chart->invalidate();
}
}
I've tried using the following code :php[7508]
PHP Fatal error: Call to a member function invalidate() on a non-object in C:\Program Files\CodeGear\Delphi for PHP\2.0\vcl\teechart\axis\AxisLabelItem.php on line 47
Finally I had to modify AxisLabelItems::clear
public function clear() {
unset($this);
$this->iAxis->chart->invalidate();
}
to remove the call to invalidate after $this has been destroyed in the prior line of code. Otherwise again PHP complains and obviously aborts processing.
That removed we have been able to, finally, make the test harness work.
Code: Select all
$chart->getChart()->getAxes()->getBottom()->getLabels()->getItems()->clear();
$chart->getChart()->getAxes()->getBottom()->getLabels()->setStyle(AxisLabelStyle::$TEXT);
$chart->getChart()->getAxes()->getBottom()->getLabels()->getItems()->add(0,"mylabel");
Code: Select all
public function clear() {
unset($this);
$this->iAxis->chart->invalidate();
}
Pep Jorge
http://support.steema.com
http://support.steema.com