SRGraphLabelBlock Class Overview

The SRGraphLabelBlock is a class which contains and manages a variable length linked list of SRGraphLabel objects.

The position and orientation of a block of labels is defined by the m_ptStart and m_ptEnd members. These CPoint objects are the end points of an imaginary line along which the labels may be placed at set intervals. A member function SRGraphLabelBlock::SetBlockPositions will automatically position any labels contained in the block along that line. Furthermore if that line is not perpendicular to the screen x or y axes then the labels will be rotated to an angle which will place them perpendicular to the line drawn between the two anchor points.

In any given list of labels the situation may arise where the text of one label will overlap the text of another. To reduce or eliminate this problem a label block has the ability to remove or displace labels. In the case of simple label blocks the labels which overlap are removed from view but not removed from the list. This means for example that if the block is being used to annotate a graph axis which is zoomed out, zooming in on the axis will reveal more detail and in turn more labels. The anti collision system will also move labels on a pre-programmed vector until they no longer overprint their neighbours. Vectors may be set to all be in the same direction in which case the label list will progressively stagger the labels in neat tiers of two then three or more rows. Vectors may also be set in any arbitrary direction in which case the label will simply wander off until it no longer interferes with another. An example of this is the pie chart label block which gives each label a vector consistent with the angle described from the centre of the pie through the centre of the wedge and on out into the space beyond.

To facilitate the generation of tick marks and grid-lines which are positioned accurately next to the labels the SRGraphLabelBlock can automatically fill an array of CPoint objects with the positions of its labels as the draw cycle progresses. This array may then be used to draw the ticks and grids exactly at the position of the labels.

As a label block is drawn, all the extents of all the labels are accumulated into a rectangle. The sizes of this rectangle can be used to move other items, like the m_DisplayRect dimensions, so that axis and data do not overprint the labels. To better calculate the positions and sizes a two pass system is employed. It is true that when a graph is being drawn the labels will eat away at the available surface area which the display can use. This may in turn mean that a reduced display area will further diminish the space available to labels by shortening the length of the axes. To prevent a catch 22 deadlocking the labels can be told to draw a "pass 0" or "pass 1" set. Pass 0 will perform all the calculations and return an estimated size without actually placing text on the screen. Pass 1 will also perform calculations but will have already taken into account the reduction in display area which they themselves have caused. Any minor label collisions which take place in pass 1 will be much less noticeable.

SRGraphLabelBlock, even though it draws the labels themselves as true components with panels, borders and shadows, will not draw such items for itself. Furthermore the labels are normally text only and do not have the normal component aesthetics turned on. If you want to see panels you may program each individual label to show its own panel or you can place the label list on top of a dummy SRGraphBackground panel.