How to place a calculated legend in a ExtraLegend

TeeChart VCL for Borland/CodeGear/Embarcadero RAD Studio, Delphi and C++ Builder.
Post Reply
Errol
Newbie
Newbie
Posts: 29
Joined: Mon Jul 08, 2019 12:00 am

How to place a calculated legend in a ExtraLegend

Post by Errol » Tue Nov 01, 2022 10:14 pm

I use TeeChart with a Self Stacked bar chart to visualise the stratigraphy down a well. I have code to generate the legend as shown in the attached image, Stratigraphy.jpg.

However, I wish to create a split-chart with the stratigraphy on the left and a line chart on the right, I am unable to show both legends, as in StratigraphyPT.jpg. How can I place both legends on the chart. I would prefer to be able to create an ExtraLegend and then assign this to the series at the appropriate point.

I have created an ExtraLegend tool as shown below, but I don't understand how to now apply the legend code to the ExtraLegend.

Code: Select all

  if self.owner.fToggleSecondWorksheet then
  begin
    ExtraLegend := TExtraLegendTool.Create(self.owner);
    self.Owner.Chart.Tools.Add(ExtraLegend);
    ExtraLegend.Series := TUnitBarSeries(SeriesListB.Objects[iIndex]);
  end;
Attachments
StragraphyPT.jpg
StragraphyPT.jpg (128.36 KiB) Viewed 3727 times
Stragraphy.jpg
Stragraphy.jpg (97.54 KiB) Viewed 3727 times

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

Re: How to place a calculated legend in a ExtraLegend

Post by Yeray » Wed Nov 02, 2022 1:02 pm

Hello Errol,

You could override the TeeExtraLegendTool's ChartEvent to set ShowInLegend for those series you want it to consider, and reset ShowInLegend at the Chart's OnBeforeDrawChart for the main legend. Ie:
extralegend.png
extralegend.png (7.59 KiB) Viewed 3711 times

Code: Select all

uses Series, TeeExtraLegendTool;

type TMyExtraLegendTool=class(TExtraLegendTool)
  protected
    procedure ChartEvent(AEvent: TChartToolEvent); override;
end;

TLegendAccess=class(TChartLegend);

procedure TMyExtraLegendTool.ChartEvent(AEvent: TChartToolEvent);
begin
  inherited;

  if AEvent=cteAfterDraw then
  begin
    ParentChart[0].ShowInLegend:=False;
    ParentChart[1].ShowInLegend:=True;
    ParentChart[2].ShowInLegend:=True;

    if Assigned(ParentChart) and Assigned(Series) then
    begin
      Legend.Series:=Series; // call getter

      if Legend.Visible then
      begin
        TLegendAccess(Legend).CalcRect;
        Legend.DrawLegend;
      end;
    end;
  end;
end;

procedure TForm1.Chart1BeforeDrawChart(Sender: TObject);
begin
  Chart1[0].ShowInLegend:=True;
  Chart1[1].ShowInLegend:=False;
  Chart1[2].ShowInLegend:=False;
end;

procedure TForm1.FormCreate(Sender: TObject);
var i: Integer;
begin
  Chart1.View3D:=False;
  Chart1.Gradient.Visible:=False;
  Chart1.Color:=clWhite;
  Chart1.Walls.Back.Gradient.Visible:=False;
  Chart1.Walls.Back.Color:=clWhite;

  Chart1.Axes.Bottom.EndPosition:=50;
  Chart1.Axes.Top.StartPosition:=50;

  with TBarSeries(Chart1.AddSeries(TBarSeries)) do
  begin
    MultiBar:=mbSelfStack;
    Marks.Hide;
    FillSampleValues(3);
  end;

  with TLineSeries(Chart1.AddSeries(TLineSeries)) do
  begin
    HorizAxis:=aTopAxis;
    Pointer.Show;
    Pointer.Size:=2;
    FillSampleValues(5);
  end;

  with TLineSeries(Chart1.AddSeries(TLineSeries)) do
  begin
    HorizAxis:=aTopAxis;
    Pointer.Show;
    Pointer.Size:=2;
    FillSampleValues(5);
  end;

  Chart1.Draw;

  with TMyExtraLegendTool(Chart1.Tools.Add(TMyExtraLegendTool)) do
  begin
    Series:=Chart1[1];
    Legend.LegendStyle:=lsSeries;
    Legend.Left:=Chart1.Legend.Left;
    Legend.Top:=Chart1.Legend.Top+Chart1.Legend.Height+10;
  end;
end;
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

Errol
Newbie
Newbie
Posts: 29
Joined: Mon Jul 08, 2019 12:00 am

Re: How to place a calculated legend in a ExtraLegend

Post by Errol » Sun Nov 06, 2022 5:17 am

Hello Yeray

Thank you for your reply. I have reviewed your sample code, but I am still puzzled on how to proceed. In my code, I use a single chart and a single legend for any number of line series (see multiline.jpg with 4 series and a single combined legend). Similarly, for bar charts (multigeology.jpg).

When I make a chart with both line and bar charts, I would like to simply assign the bar chart legend (a composite legend of all rock types in the selected series) to an ExtraLegend, rather than change all my code to refer to chart[0], chart[1] etc, as would seem to be necessary if I added each series to the chart. Is this possible?
Attachments
Multigeology.jpg
Multigeology.jpg (219.91 KiB) Viewed 3684 times
Multiline.jpg
Multiline.jpg (145.39 KiB) Viewed 3684 times

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

Re: How to place a calculated legend in a ExtraLegend

Post by Yeray » Mon Nov 07, 2022 2:41 pm

Hello Errol,

If you want TBarSeries in the main series and TLineSeries in the extra legend, you can loop all the series and activate/deactivate ShowInLegend according to the series class:

Code: Select all

uses Series, TeeExtraLegendTool;

type TMyExtraLegendTool=class(TExtraLegendTool)
  protected
    procedure ChartEvent(AEvent: TChartToolEvent); override;
end;

TLegendAccess=class(TChartLegend);

procedure TMyExtraLegendTool.ChartEvent(AEvent: TChartToolEvent);
var i: Integer;
begin
  if AEvent=cteAfterDraw then
  begin
    for i:=0 to ParentChart.SeriesCount-1 do
        ParentChart[i].ShowInLegend:=ParentChart[i] is TLineSeries;

    if Assigned(ParentChart) and Assigned(Series) then
    begin
      if Legend.Visible then
      begin
        TLegendAccess(Legend).CalcRect;
        Legend.DrawLegend;
      end;
    end;
  end;
end;

procedure TForm1.Chart1BeforeDrawChart(Sender: TObject);
var i: Integer;
begin
  for i:=0 to Chart1.SeriesCount-1 do
      Chart1[i].ShowInLegend:=Chart1[i] is TBarSeries;
end;

procedure TForm1.FormCreate(Sender: TObject);
var i: Integer;
begin
  Chart1.View3D:=False;
  Chart1.Gradient.Visible:=False;
  Chart1.Color:=clWhite;
  Chart1.Walls.Back.Gradient.Visible:=False;
  Chart1.Walls.Back.Color:=clWhite;

  Chart1.Axes.Bottom.EndPosition:=50;
  Chart1.Axes.Top.StartPosition:=50;

  Chart1.OnBeforeDrawChart:=Chart1BeforeDrawChart;

  with TBarSeries(Chart1.AddSeries(TBarSeries)) do
  begin
    MultiBar:=mbSelfStack;
    Marks.Hide;
    FillSampleValues(3);
  end;

  with TLineSeries(Chart1.AddSeries(TLineSeries)) do
  begin
    HorizAxis:=aTopAxis;
    Pointer.Show;
    Pointer.Size:=2;
    FillSampleValues(5);
  end;

  with TLineSeries(Chart1.AddSeries(TLineSeries)) do
  begin
    HorizAxis:=aTopAxis;
    Pointer.Show;
    Pointer.Size:=2;
    FillSampleValues(5);
  end;

  Chart1.Draw;

  with TMyExtraLegendTool(Chart1.Tools.Add(TMyExtraLegendTool)) do
  begin
    Series:=Chart1[1];
    Legend.LegendStyle:=lsSeries;
    Legend.Left:=Chart1.Legend.Left;
    Legend.Top:=Chart1.Legend.Top+Chart1.Legend.Height+10;
  end;
end;
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