TAChart: some fixes for TAFuncSeries unit
Original Reporter info from Mantis: Marcin Wiazowski
-
Reporter name:
Original Reporter info from Mantis: Marcin Wiazowski
- Reporter name:
Description:
I'm attaching a patch, that solves a group of related problems in TAFuncSeries unit.
Test 1: Load the attached Reproduce application and start it. An exception 'External: SIGSEGV' will be raised immediately due to a null pointer dereference - this is because TFuncSeries.OnCalculate handler is not assigned.
So there is no validation for the handler - although there should be.
Test 2: In Object Inspector, set Chart2FuncSeries' OnCalculate handler to Chart2FuncSeriesCalculate (so application will be able to work properly). Now take a look at the designed form, at the middle (TFuncSeries) chart - it's X axis range is -1 .. 1 (it uses ExtentAutoY functionaliy, so Y axis range is same). Now launch the application - X axis range is changed to 0 .. 500.
For both left chart (holding TExpressionSeries) and middle chart (holding TFuncSeries), series' Extent property is defined in the same way, forcing X range to be 0 .. 500. At design time, this works properly only for TExpressionSeries. But at runtime, this works properly for both TExpressionSeries and TFuncSeries.
This is because TFuncSeries.GetBounds() is implemented in a strange way:
procedure TFuncSeries.GetBounds(var ABounds: TDoubleRect);
begin
if (csDesigning in ComponentState) then
exit;
inherited GetBounds(ABounds);
end;
Maybe, some time ago, there was a reason for doing this, but currently this can work properly also at design time - exactly as it is in TExpressionSeries.
Now some note: TFuncSeries and TParametricCurveSeries use their OnCalculate events to draw the series. But, at design time, OnCalculate handler cannot be used - so, in order to show some visual feedback to the user, an internal DoCalcIdentity() function is used - so a straight line is drawn.
The attached patch:
-
Removes TFuncSeries.GetBounds() method, so ancestor's GetBounds() is used - thanks to that, proper X axis range is shown also at design time. This solves the problem described in Test 2.
-
Now the TFuncSeries.DoCalculate() and TParametricCurveSeries.DoCalculate() methods encapsulate the "DoCalcIdentity()" behavior, making the code concise. And, to prevent null pointer dereferences (as described in Test 1), an exception is raised in case of uninitialized OnCalculate event.
-
The TFuncSeries.IsEmpty() and TParametricCurveSeries.IsEmpty() methods work improperly now. They are implemented as:
function XXX.IsEmpty: Boolean;
begin
Result := not Assigned(OnCalculate);
end;
As described above, at design time, an internal "DoCalcIdentity()" behavior is used, so series is NOT in fact empty. So "and not (csDesigning in ComponentState)" expressions have been added to fix this.
-
A needless "if (csDesigning in ComponentState)" expression has been removed in TColorMapSeries.FunctionValue().
-
Since TExpressionSeries and TFuncSeries use TIntervalList helper object internally, improper validation in TIntervalList.Intersect() has also been fixed.