How to clone a chart if it has tools?

TeeChart VCL for Borland/CodeGear/Embarcadero RAD Studio, Delphi and C++ Builder.
Post Reply
jens.mertelmeyer
Newbie
Newbie
Posts: 60
Joined: Fri Nov 22, 2013 12:00 am

How to clone a chart if it has tools?

Post by jens.mertelmeyer » Fri May 23, 2014 6:55 pm

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. 8)

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
chart deep copy.png (49.93 KiB) Viewed 8984 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.

Yeray
Site Admin
Site Admin
Posts: 9602
Joined: Tue Dec 05, 2006 12:00 am
Location: Girona, Catalonia
Contact:

Re: How to clone a chart if it has tools?

Post by Yeray » Mon May 26, 2014 10:39 am

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
Best Regards,
ImageYeray Alonso
Development & Support
Steema Software
Av. Montilivi 33, 17003 Girona, Catalonia (SP)
Image Image Image Image Image Image Please read our Bug Fixing Policy

jens.mertelmeyer
Newbie
Newbie
Posts: 60
Joined: Fri Nov 22, 2013 12:00 am

Re: How to clone a chart if it has tools?

Post by jens.mertelmeyer » Tue May 27, 2014 8:11 am

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
chart deep copy - success.png (47.84 KiB) Viewed 8938 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.

Yeray
Site Admin
Site Admin
Posts: 9602
Joined: Tue Dec 05, 2006 12:00 am
Location: Girona, Catalonia
Contact:

Re: How to clone a chart if it has tools?

Post by Yeray » Tue May 27, 2014 2:04 pm

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!
Best Regards,
ImageYeray Alonso
Development & Support
Steema Software
Av. Montilivi 33, 17003 Girona, Catalonia (SP)
Image Image Image Image Image Image Please read our Bug Fixing Policy

Post Reply