Page 1 of 1

when to position custom axes?

Posted: Wed Apr 19, 2006 5:08 pm
by 9338026
Hi,

We are now using custom axes for our data, so that we can place the axis in the correct position at the 0 value, while still displaying the titles outside the chart itself. We are displaying the ticks and labels on the custom axes. We are using the default bottomAxis and LeftAxis for displaying the titles.

Unfortunately, we can't figure out exactly when it is appropriate to set the position of the custom axes. Basically, this has to happen after the chartRect has been set, but before the axes have been fixed into place.

We've tried several events, like beforeDrawChart, beforeDrawSeries, beforeDrawAxes, but none seems perfectly appropriate - either the chartrect is not yet set, or the axes have already been positioned, and don't get repositioned to where we want.

Is there an event where it is appropriate to do this?

Thanks,
Dave

Posted: Thu Apr 20, 2006 8:04 am
by narcis
Hi Dave,

You should do it in the OnAfterDraw event. Please find below a VB example doing what you request. You shouldn't have much problems porting it to TeeChart VCL version.

Code: Select all

Private Sub Form_Load()
    For i = -5 To 10
        TChart1.Series(0).AddXY i, i, "", clTeeColor
    Next i
    
    TChart1.Panel.MarginUnits = muPixels
    
    TChart1.Environment.InternalRepaint
    
End Sub

Private Sub TChart1_OnAfterDraw()
  With TChart1.Axis
    
    If usePercentages = True Then
        
         chartWidth = .Right.Position - .Left.Position
         horizZeroLoc = .Bottom.CalcXPosValue(0) - .Left.Position
         horizPercentLoc = horizZeroLoc / chartWidth * 100

        .Left.PositionUnits = puPercent
        .Left.PositionPercent = horizPercentLoc

         chartHeight = .Bottom.Position - .Top.Position
         vertZeroLoc = .Left.CalcYPosValue(0) - .Top.Position
         vertPercentLoc = vertZeroLoc / chartHeight * 100

        .Bottom.PositionUnits = puPercent
        .Bottom.PositionPercent = 100 - vertPercentLoc
        
    Else
        
        .Left.PositionUnits = puPixels
        .Left.PositionPercent = .Bottom.CalcXPosValue(0) - .Left.Position
        
        .Bottom.PositionUnits = puPixels
        .Bottom.PositionPercent = .Bottom.Position - .Left.CalcYPosValue(0)
                              
    End If
    
  End With
End Sub

Posted: Thu Apr 20, 2006 8:12 am
by 9338026
Hi Narcis,

We had a bunch of issues with this. We did not think that putting it in the afterDraw would work because then when drawing to a bitmap it would not work because the axis would be drawn initially in the wrong place, then in the right place, so there would be two lines.

We eventually had to do a couple of things
1) set the option to draw the axes on top of the series
2) set the custom position in the onAfterDrawSeries event

There was still a problem, because the label position is calculated before the series are drawn, when the axes are still in the wrong position. So even though the axes were where we wanted them, the labels were in the "old" place. When we adjusted the positionPercent of the customAxis, it did not update the labelPos of the custom Axis' labels. So we had to modify the tchartAxis code to include a method that allowed us to force the labelPos to be updated based upon the current posAxis. I think that this is a bug personally, and that the labelPos should be updated automatically everytime the axisPos changes, but maybe this would cause other problems. It works fine for us though.

Posted: Thu Apr 20, 2006 8:50 am
by narcis
Hi Dave,

The TChart1.Environment.InternalRepaint call done in the snippet I posted is similar to Chart1.Draw. You can use it to force the chart being drawn so all positions are already where they should so your objects are placed properly. Be very careful using it because you can easily fall in a infinite loop.

Posted: Thu Apr 20, 2006 8:58 am
by 9338026
Hi Narcis,

Thank you. I will investigate that. I did not know about the environment property.

If you guys ever consider a refactor, I would hope you could find a way to break the position calculation code away from the drawing code. All of the plots elements should be calculated first, before anything is drawn. Then, after they are all calculated, users get a chance to modify them and perhaps force another recalculation. Then, when everything is ready, the plots are finally drawn.

Posted: Thu Apr 20, 2006 9:33 am
by narcis
Hi Dave,
Thank you. I will investigate that. I did not know about the environment property.
Please notice that environment property is for TeeChart ActiveX, in VCL version you'll need to use Draw or Invalidate methods.
If you guys ever consider a refactor, I would hope you could find a way to break the position calculation code away from the drawing code. All of the plots elements should be calculated first, before anything is drawn. Then, after they are all calculated, users get a chance to modify them and perhaps force another recalculation. Then, when everything is ready, the plots are finally drawn.
I'm afraid it is pretty dificult as many objects depend on other chart objects to be drawn and they can be positioned until those elements are drawn. However, most cases can be sorted combining TChart events and Draw method calls.