Steema Issues Database

Note: This database is for bugs and wishes only. For technical support help, if you are a customer please visit our online forums;
otherwise you can use StackOverflow.
Before using this bug-tracker we recommend a look at this document, Steema Bug Fixing Policy.



Bug 780

Summary: [TV52016721] Cloning a Chart copies the series to the destination chart, and it al...
Product: VCL TeeChart Reporter: yeray alonso <yeray>
Component: SeriesAssignee: yeray alonso <yeray>
Status: RESOLVED FIXED    
Severity: enhancement CC: mertelmeyer
Priority: Normal    
Version: unspecified   
Target Milestone: ---   
Hardware: All   
OS: All   
Chart Series: --- Delphi / C++ Builder RAD IDE Version:

Description yeray alonso 2014-05-26 06:57:11 EDT
Cloning a Chart copies the series to the destination chart, and it also copies the custom axes, but not the CustomVertAxis and CustomHorizAxis links.
Not sure if this has to be done in the Assign(), in the AssignFormat(), or in the CloneChart() method, at TeEngine.pas:
TChartSeries.AssignFormat(Source:TChartSeries)
TChartSeries.Assign(Source:TPersistent);
CloneChart(Dest,Origin:TCustomChart; AOwner:TComponent; ForceManualData:Boolean);
http://www.teechart.net/support/viewtopic.php?f=3&t=14354&p=63137#p63137
Here it is the code to reproduce the problem. You just need two empty charts in a form:
uses Series;
procedure TForm1.FormCreate(Sender: TObject);
var i, nSeries: Integer;
begin
  nSeries:=4;
  Chart1.View3D:=false;
  Chart1.MarginLeft:=10;
  for i:=0 to nSeries-1 do
  begin
    Chart1.AddSeries(TLineSeries).FillSampleValues;
    with Chart1.CustomAxes.Add as TChartAxis do
    begin
      StartPosition:=i*100/nSeries;
      EndPosition:=(i+1)*100/nSeries;
      Axis.Color:=Chart1[i].Color;
      LabelsFont.Color:=Chart1[i].Color;
    end;
    Chart1[i].CustomVertAxis:=Chart1.CustomAxes[i];
  end;
  //Clone Chart1 to Chart2
  CloneChart(Chart2, Chart1, Self, false);
end;

As a workaround, if you know the relations, you can reassign them as follows, but what if you don't?
  for i:=0 to Chart2.SeriesCount-1 do
    Chart2[i].CustomVertAxis:=Chart2.CustomAxes[i]; [created:2013-09-17T16:41:54.000+02:00 reported by:yeray@steema.com reported in version:2013.08.030521 (TeeChart VCL)]
Comment 1 yeray alonso 2014-05-27 10:09:38 EDT
Another customer suggested another workaround using a Dictionary to save the correlations between the axes in the original and destination charts.
The customer uses this dictionary to set the Series and Axis properties in the tools in the destination chart.

Worth to take a look at when implementing the fix.

http://www.teechart.net/support/viewtopic.php?p=66163#p66163

Here the code:

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;