Page 1 of 1

Bar Chart vertical self-stacked title position

Posted: Wed Dec 07, 2022 4:05 am
by 16566546
Good afternoon

I have a persistent problem with placing a title above self-stacked bar charts. My code works correctly if the bottom axis has specified scaling, but not if the scaling is automatic. The (edited) procedure I use is shown below.

Code: Select all

    
procedure TPBQuickGraph.PlaceWellNames;
var
  h, LLeft, LWidth, LHeight: integer;
  LAcross: integer;
  LRect: TRect;

for h := 1 to fIntervalQueryCollection.SeriesListB.Count - 1 do
begin
  with (Chart.Tools[h] as TAnnotationTool) do
  begin
    Shape.CustomPosition := true;
    Shape.Pen.Color := clWhite;
    Shape.Transparent := true;
    Shape.Font.Size := fBarNameFont;
    Shape.Font.Style := Shape.Font.Style + [fsBold];
    Shape.Angle := fBarNameDir;
    PositionUnits := muPixels;
    Text := aWellName[h];

    // centre of bar, I think
    LLeft := TUnitBarSeries(fIntervalQueryCollection.SeriesListB.Objects[h]).CalcXPos(0);

    LWidth := Width;   // width of shape??
    LAcross := LWidth div 2   // half title width

    if Chart.BottomAxis.Automatic then
    begin
      Left := LLeft - LAcross + fBarWidth Div 2;  // this sort of works but varies according to bar width
    end
    else
      Left := LLeft - LAcross;  // this is correct for non-automatic scaling
  end;    
end;
The PlaceWellNames procedure is called in ChartBeforeDrawSeries, ChartAfterDraw as well as Zoom, UndoZoom and ChartScroll.

Thanks and regards

Errol

Re: Bar Chart vertical self-stacked title position

Posted: Fri Dec 09, 2022 5:53 pm
by yeray
Hello Errol,

I've done a simple example with 3 self-stacked bars and 3 annotation tools.
I'm using TAnnotationTool.OnBeforeDraw event to calculate the position of the tool and it should work both for automatic and custom axis scales, and also for scrolling and zooming:

Code: Select all

uses Series, TeeTools;

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

  for i:=0 to 2 do
  begin
    with TBarSeries(Chart1.AddSeries(TBarSeries)) do
    begin
      MultiBar:=mbSelfStack;
      Marks.Hide;
      for j:=0 to 4 do
        Add(5+Random*5);
    end;

    with TAnnotationTool(Chart1.Tools.Add(TAnnotationTool)) do
    begin
      Shape.CustomPosition := true;
      Shape.Pen.Color := clWhite;
      Shape.Transparent := true;
      //Shape.Font.Size := fBarNameFont;
      Shape.Font.Style := Shape.Font.Style + [fsBold];
      //Shape.Angle := fBarNameDir;
      //Text := aWellName[h];
      Text:='Well ' + IntToStr(i+1);

      OnBeforeDraw:=AnnotationToolBeforeDraw;
    end;
  end;

  Chart1.Axes.Bottom.SetMinMax(-1, 3);

  Chart1.Draw;
end;

procedure TForm1.AnnotationToolBeforeDraw(Sender: TObject);
var i: Integer;
begin
  for i:=0 to Chart1.Tools.Count-1 do
    if Sender = Chart1.Tools[i] then
    begin
      PlaceWellNames(i);
      Exit;
    end;
end;

procedure TForm1.PlaceWellNames(AIndex: Integer);
var
  LLeft, LWidth: integer;
  LAcross: integer;
  annot: TAnnotationTool;
  bar: TBarSeries;
begin
  if Chart1.Tools[AIndex] is TAnnotationTool then
  begin
    annot:=TAnnotationTool(Chart1.Tools[AIndex]);
    bar:=TBarSeries(Chart1[AIndex]);

    // centre of bar
    LLeft := bar.CalcXPos(0) + (bar.BarWidth div 2);
    LWidth := annot.Width;   // width of shape
    LAcross := LWidth div 2;   // half title width

    annot.PositionUnits := muPixels;
    annot.Left := LLeft - LAcross;  // this is correct for non-automatic scaling
  end;
end;