Page 1 of 1
How to clone a chart if it has tools?
Posted: Fri May 23, 2014 6:55 pm
by 16567885
The method
Code: Select all
procedure CloneChart(Dest, Origin: TCustomChart; AOwner: TComponent; ForceManualData: Boolean);
from
VclTee.Chart makes it easy to make a deep copy of a chart. Difficult to find, but very cool.
I have two questions:
- What does the parameter ForceManualData stand for? The documentation does not say anything
- How should one go about copying a chart that has tools?
Let's consider the attached example screenshot:
- chart deep copy.png (49.93 KiB) Viewed 9164 times
On the left, the original chart has a TGridBandTool as well as a region tool. The right chart obviously doesn't have those. Here is my code:
Code: Select all
var
chartToolIterator, clonedTool: TTeeCustomTool;
begin
// Copy the chart
newChart := TChart.Create(self);
VclTee.Chart.CloneChart(
newchart,
chart1,
self,
False
);
newChart.Parent := panel1;
newChart.Align := TAlign.alClient;
// Everything fine so far, let's copy the tools
for chartToolIterator in chart1.Tools do begin
clonedTool := VclTee.Chart.CloneChartTool(
chartToolIterator,
self
);
clonedTool.ParentChart := newChart;
newChart.Tools.Add(clonedTool);
end;
end;
Anything unusual with that? I believe those two examples don't work because they still point to the axes of the original chart. That would also explain why stuff like a "cursor" can be copied over to another chart without problems.
Any suggestions or workarounds? Basically, I just want to create an exact copy of a chart.
Many thanks in advance.
Re: How to clone a chart if it has tools?
Posted: Mon May 26, 2014 10:39 am
by yeray
Hello,
Sounds like the same problem explained
here, where the Clone function would be missing to move the relations between tools and axes to the new tools and axes in the second chart.
Please check if the workaround suggested there works fine for you.
Also feel free to add your mail to the CC list of the public ticket so you can be automatically notified when an update arrives:
http://bugs.teechart.net/show_bug.cgi?id=780
Re: How to clone a chart if it has tools?
Posted: Tue May 27, 2014 8:11 am
by 16567885
Thank you for your reply
The problem is indeed the same, I however don't quite understand your workaround. I find it much easier to clone all tools and check them if they're an instance of TTeeCustomToolSeries or TTeeCustomToolAxis and adjust them to the new chart, if necessary.
This way, I now have a nice copy I'm happy with:
- chart deep copy - success.png (47.84 KiB) Viewed 9118 times
In case you're interested, this is how I cloned the tools. If you got the time, would you mind having a quick look at it? I'm not sure if I overlooked something (except handling the
TTeeCustomAnimation subclass of
TTeeCustomTool).
Code: Select all
class procedure TTeeChartRenderer.cloneTools(
const fromChart: TChart;
const toChart: TChart
);
var
axisLookupDict: IDictionary<TChartAxis, TChartAxis>;
toolIterator: TTeeCustomTool;
copiedTool: TTeeCustomTool;
begin
Assert( Assigned(fromChart) and Assigned(toChart) );
// This is a lookup dictionary to find the matching axis of "toChart"
// when we still have the "old" axis of "fromChart"
axisLookupDict := createAxisDictionary(fromChart, toChart);
for toolIterator in fromChart.Tools do begin
copiedTool := VclTee.Chart.CloneChartTool(toolIterator, toChart);
// Point tool to matching series of toChart
if toolIterator is TTeeCustomToolSeries then
(copiedTool as TTeeCustomToolSeries).Series :=
toChart.Series[ (toolIterator as TTeeCustomToolSeries).Series.SeriesIndex ];
// Point tool to matching axis of toChart
if toolIterator is TTeeCustomToolAxis then
(copiedTool as TTeeCustomToolAxis).Axis :=
axisLookupDict[ (toolIterator as TTeeCustomToolAxis).Axis ];
toChart.Tools.Add(copiedTool);
end;
end;
class function TTeeChartRenderer.createAxisDictionary(
const originalChart: TChart;
const clonedChart: TChart
): IDictionary<TChartAxis, TChartAxis>;
var
axisIndex: Integer;
begin
Assert( Assigned(originalChart) and Assigned(clonedChart) );
Result := TDictionary<TChartAxis, TChartAxis>.Create();
try
{TODO -oJM -cGeneral : Does that that also include "custom axes"?}
for axisIndex := 0 to Pred(originalChart.Axes.Count) do
Result.Add(
originalChart.Axes.Items[axisIndex],
clonedChart.Axes.Items[axisIndex]
);
except
Result.Free();
raise;
end;
end;
Best regards.
Re: How to clone a chart if it has tools?
Posted: Tue May 27, 2014 2:04 pm
by yeray
Hi,
Your workaround looks great for setting the Series and Axis properties in the destination chart.
Note that my workaround was to save a slightly different situation, where the original chart has custom axes and the relations between the series in the original chart and these custom axes have to be moved to the new series and custom axes in the destination chart.
Your solution using a Dictionary is really a point to consider. I'll add it to the ticket so it can be studied, adapted and maybe included in the sources when the fix will be implemented.
Thanks for sharing!