On 10 Nov 2008, at 1:01 am, Joseph Ayers wrote:

I am having a tremendous problem getting the vertical text in the y Axis of a graph. If i try to rotate text specified as NSAttributedString it appears to get translated in nonlinear ways: I would assume that in the below, the text would
rotate around NSMinX(rect) and NSMinY(rect) but it doesn't.

Consider:
- (void)drawYLabel:(NSRect)rect
{

        NSPoint labelHere;
        int xOffSet;
        if(drawYLabelFlag == YES)
                {
                        NSAffineTransform *transform = [NSAffineTransform 
transform];
                        NSGraphicsContext *context   = [NSGraphicsContext 
currentContext];
                        
//                      [transform translateXBy:NSMinY(gRect) yBy:0.0];
                        [transform rotateByDegrees:90.0];

                        [context saveGraphicsState];
                        [transform concat];
                        
                        xOffSet =NSMinY(rect) + ((gHeight/2.0)  - [ylabel 
size].width/2.0);
labelHere = NSMakePoint( xOffSet, NSMinY(rect) +[ylabel size].height) ;
                        [ylabel drawAtPoint:labelHere];
                        
                        [context restoreGraphicsState];
                }
}
yLabel is a NSAttributed String
gHeight is the height of rect.
rect is a bounding rect for the graph that is smaller than the frame of the NSView.

yLabel doesn't appear in the NSView

What am I doing wrong here


Any rotation is with respect to the origin of the coordinate system. Thus, to rotate about a given point, you need to make that point the origin, perform the rotation, then translate back to the actual position you want to draw.

Thus (typed into mail):

NSAffineTransform* transform = [NSAffineTransform transform];

[transform translateXBy:myPoint.x yBy:myPoint.y];
[transform rotateByDegrees:90];
[transform translateXBy:-myPoint.x yBy:-myPoint.y];
[transform concat];

[myAttributedString drawAtPoint:myPoint];


Note that the translation to the origin and back is apparently back-to- front. Transforms are like that - I find it sometimes helps to read the series of translate/scale/rotate operations in reverse order to get an idea of what it does as if in a series of steps.

Anyway, in your code you need to figure the origin of your drawing rect and do the above. Your code refers to 'gRect' but uses 'rect' - not clear if that's intentional or what it means. But if your label is drawn in the rect 'rect' then you should be able to use that information alone to handle the rotation, so I'm not sure what gRect is or how it's being used.

Anyhoo, hope that helps.

Here's some code I have in my current app that does something similar, labelling the axes of a grid. It refers to other methods and so on not shown here, but will give you an idea of how I do the rotation. One thing to note is that I do all of the positioning calculations ahead of doing the rotation/drawing. Also, <aRect> is the updateRect that originates in the view's -drawRect: method, not the box in which I draw the text. This also handles both X and Y axes, hence the added complication ;-)



- (void) drawAnnotationElement:(unsigned) indx maxElement:(unsigned) max inRect:(NSRect) aRect atEdge:(DKOGridEdge) edge
{
//<indx> is the ordinal item to draw, starting from 0. The actual drawn element factors in the offset and increment. <edge> specifies which edge(s) the annotation // should be drawn at. It will be left or right. For vertical annotation left == top, right == bottom.
        
        if( edge == 0 )
                return;         // nothing to do
        
        NSString*       str = [self annotationStringForElement:indx 
maxElement:max];
NSAttributedString* std = [[NSAttributedString alloc] initWithString:str attributes:[self textAttributes]];
        NSRect  bbox, ir;
        
        // get the bounding box for the string

        bbox.size = [std size];
        ir = [mGridRef borderRect];
        
        // swap the box width/height if rotated
        
        if([self isRotated])
        {
                float temp = bbox.size.width;
                bbox.size.width = bbox.size.height;
                bbox.size.height = temp;
        }
        
        // position the box
        
        float textOffset = [mGridRef borderAllowance] + mOffset;
        
        float sd = [mGridRef spanLength];
        
        if([self orientationIsVertical])
        {
                if( edge == kDKOLeftEdge )
                        bbox.origin.x = NSMinX( ir ) - bbox.size.width - 
textOffset;
                else
                        bbox.origin.x = NSMaxX( ir ) + textOffset;
                
bbox.origin.y = ( NSMinY( ir ) + ( sd * indx )) - (bbox.size.height * 0.5);
                
                if([self placement] == kDKOPlaceAnnotationBetweenGrid )
                        bbox.origin.y += sd * 0.5;
                
                // don't draw if beyond end of interior
                
                if( bbox.origin.y > NSMaxY( ir ))
                        return;
        }
        else
        {
                if( edge == kDKOLeftEdge )
bbox.origin.y = NSMinY( ir ) - bbox.size.height - ( textOffset * 0.7);
                else
                        bbox.origin.y = NSMaxY( ir ) + ( textOffset * 0.7 );
                
bbox.origin.x = ( NSMinX( ir ) + ( sd * indx )) - (bbox.size.width * 0.5);
                
                if([self placement] == kDKOPlaceAnnotationBetweenGrid )
                        bbox.origin.x += sd * 0.5;
                
                if( bbox.origin.x > NSMaxX( ir ))
                        return;
        }
        
        // draw the text in the box
        
        if( NSIntersectsRect( bbox, aRect ))
        {
                NSPoint         origin = bbox.origin;
                
                [NSGraphicsContext saveGraphicsState];
                
                if([self isRotated])
                {
                        NSAffineTransform* tfm = [NSAffineTransform transform];
                        
                        if([self orientationIsVertical])
                        {
                                origin.x = NSMaxX( bbox );
                                [tfm translateXBy:origin.x yBy:origin.y];
                                [tfm rotateByDegrees:90];
                                [tfm translateXBy:-origin.x yBy:-origin.y];
                        }
                        else
                        {
                                origin.y = NSMaxY( bbox );
                                [tfm translateXBy:origin.x yBy:origin.y];
                                [tfm rotateByDegrees:-90];
                                [tfm translateXBy:-origin.x yBy:-origin.y];
                        }
                        [tfm concat];
                }
                
                [std drawAtPoint:origin];
                [NSGraphicsContext restoreGraphicsState];
        }
}



Graham
_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]

Reply via email to