Page 1 of 1

Annotation goes off right side of chart

Posted: Thu Nov 20, 2014 12:08 am
by 10546565
In the attached demo, I have a couple chart tools--one a TColorLineTool that I place at a specific location on the X (bottom) axis, and a annotation tool that I try to place right over the line to note the lines purpose.

If the line appears on the right side of the chart, I try to position the annotation so that it shifts right as not to cut off the text in the annotation--I even add margin for this. Here is my code for it:

Code: Select all

  procedure SetLeftPos(aMiddle: double; aAnnTool: TAnnotationTool);
  const
    H_MARGIN = 50;
  var
    lLeft: Integer;
    lR: TRect;
    lAnnWidth: Integer;
  begin
    if not aAnnTool.Active then
      exit;

    lLeft :=  aChart.BottomAxis.CalcXPosValue(aMiddle);
    lR := aAnnTool.Bounds;
    lAnnWidth := lR.Right- lR.Left + 1;
    aAnnTool.Shape.Left := lLeft - (Max(0, lAnnWidth) div 2);
    if aAnnTool.Shape.Left + aAnnTool.Shape.Width > (aChart.Width - H_MARGIN) then
      aAnnTool.Shape.Left := aChart.Width - H_MARGIN - aAnnTool.Shape.Width;

    aAnnTool.Shape.Top := 30;
  end;
But this can still put the annotation too far right. See here:

Image

I cannot figure out how to get this so it does not go off the right side of the chart. How can I achieve that?

A demo of this is attached.

Thank you,

Ed Dressel

Re: Annotation goes off right side of chart

Posted: Thu Nov 20, 2014 10:52 am
by yeray
Hi Ed,

It works fine using the TAnnotationTool Left property to reposition it instead of using the TAnnotationTool Shape.Left peoperty.
Ie:

Code: Select all

  procedure SetLeftPos(aMiddle: double; aAnnTool: TAnnotationTool);
  const
    H_MARGIN = 25;
  var
    lLeft: Integer;
    lR: TRect;
    lAnnWidth: Integer;
  begin
    if not aAnnTool.Active then
      exit;

    lLeft :=  aChart.BottomAxis.CalcXPosValue(aMiddle);
    lR := aAnnTool.Bounds;
    lAnnWidth := lR.Right- lR.Left + 1;
    aAnnTool.Left := lLeft - (Max(0, lAnnWidth) div 2);
    if aAnnTool.Left + aAnnTool.Shape.Width > (aChart.Width - H_MARGIN) then
      aAnnTool.Left := aChart.Width - H_MARGIN - aAnnTool.Shape.Width;

    aAnnTool.Shape.Top := 30;
  end;

Re: Annotation goes off right side of chart

Posted: Thu Nov 20, 2014 3:31 pm
by 10546565
Thank you for the quick response. This addressed part of my issue but I didn't realize there is another issue.

When rendering the chart to a graphic, if the graphic is a different size than the chart, I don't know how to get the right width of the chart.

In the attached example, I added a TImage that shows the chart but of a different size. The annotation is always in the wrong position.

How can I get this right?

Sincerely,

Ed Dressel

Re: Annotation goes off right side of chart

Posted: Fri Nov 21, 2014 11:49 am
by yeray
Hi Ed,

Debugging your application you'll see the SetLeftPos method (called at UpdateAnnotationPosition, called at Chart1BeforeDrawSeries) is executed both when the chart is being drawn on the form and when it's drawn on the bitmap.
The problem is that Chart1.Width at this line is always the same, it hasn't changed to take the width of the bitmap yet:

Code: Select all

    if aAnnTool.Left + aAnnTool.Shape.Width > Chart1.Width then
To overcome this, I've made a slight trick.
I've created a global variable:

Code: Select all

var updatingImage: Boolean;
I initialize it to false:

Code: Select all

constructor TForm1.Create(aOwner: TComponent);
begin
  inherited;

  updatingImage:=false;
  //...
I set it to true before exporting the bitmap and back to false after it:

Code: Select all

procedure TForm1.UpdateImage;
//...
begin
  updatingImage:=true;
//...
    AssignChartToGraphic(Chart1, lRect, lGraphic);
//...
  updatingImage:=false;
end;
So now at SetLeftPos I can use the chart width or the Image width depending on where I'm coming from:

Code: Select all

  procedure SetLeftPos(aMiddle: double; aAnnTool: TAnnotationTool);
  var
  //...
    chartWidth: Integer;
  //...
    if updatingImage then
      chartWidth:=imgChart.Width
    else
      chartWidth:=aChart.Width;

    if aAnnTool.Left + aAnnTool.Shape.Width > chartWidth then
      aAnnTool.Left := chartWidth - aAnnTool.Shape.Width;
  //...