Printing with CPTGraphHostingView

47 views
Skip to first unread message

Craig Hockenberry

unread,
Mar 13, 2012, 7:44:53 PM3/13/12
to coreplot-discuss
I'm using CPTGraphHostingView in a Mac app and needed to be able to
print the contents of the graph. After a bit of digging on
StackOverflow and this discussion group, I came up the the following
subclass (called GraphHostingView.) The subclass adds a new property
called "printRect" and overrides some methods needed to print a view.

From your document's view controller, you'd do something like this:

- (IBAction)printDocument:(id)sender
{
DebugLog(@"%s called", __PRETTY_FUNCTION__);

NSPrintInfo *printInfo = self.printInfo;

NSRect printRect = NSZeroRect;
printRect.size.width = (printInfo.paperSize.width -
printInfo.leftMargin - printInfo.rightMargin) *
printInfo.scalingFactor;
printRect.size.height = (printInfo.paperSize.height -
printInfo.topMargin - printInfo.bottomMargin) *
printInfo.scalingFactor;

graphHostingView.printRect = printRect;

NSPrintOperation *printOperation = [NSPrintOperation
printOperationWithView:graphHostingView printInfo:printInfo];
[printOperation runOperationModalForWindow:self.window delegate:self
didRunSelector:@selector(printOperationDidRun:success:contextInfo:)
contextInfo:NULL];
}

The implementation of GraphHostingView follows. I'd like to see these
changes get added to CPTGraphHostingView (you have my permission to
use this code however you wish.)

==== GraphHostingView.h ====

#import <CorePlot/CorePlot.h>

@interface GraphHostingView : CPTGraphHostingView
{
NSRect printRect;
}

@property (nonatomic, assign) NSRect printRect;

@end

==== GraphHostingView.m ====

#import "GraphHostingView.h"

@implementation GraphHostingView

@synthesize printRect;

- (void)drawRect:(NSRect)dirtyRect
{
[super drawRect:dirtyRect];

if (! [NSGraphicsContext currentContextDrawingToScreen]) {
NSGraphicsContext *graphicsContext = [NSGraphicsContext
currentContext];

[graphicsContext saveGraphicsState];

NSRect destinationRect = self.printRect;
NSRect sourceRect = self.frame;

// scale the view isotropically so that it fits on the printed page
CGFloat widthScale = destinationRect.size.width /
sourceRect.size.width;
CGFloat heightScale = destinationRect.size.height /
sourceRect.size.height;
CGFloat scale = MIN(widthScale, heightScale);

// position the view so that its centered on the printed page
CGPoint offset = NSZeroPoint;
offset.x = ((destinationRect.size.width - (sourceRect.size.width *
scale)) / 2.0) + destinationRect.origin.x;
offset.y = ((destinationRect.size.height - (sourceRect.size.height *
scale)) / 2.0) + destinationRect.origin.y;

NSAffineTransform *transform = [NSAffineTransform transform];
[transform translateXBy:offset.x yBy:offset.y];
[transform scaleBy:scale];
[transform concat];

// render CPTLayers recursively into the graphics context used for
printing (thanks to Brad for the tip: http://stackoverflow.com/a/2791305/132867
)
CGContextRef context = [graphicsContext graphicsPort];
[self.hostedGraph recursivelyRenderInContext:context];

[graphicsContext restoreGraphicsState];
}
}

- (BOOL)knowsPageRange:(NSRangePointer)rangePointer
{
rangePointer->location = 1;
rangePointer->length = 1;

return YES;
}

- (NSRect)rectForPage:(NSInteger)pageNumber
{
return self.printRect;
}

@end

Eric

unread,
Mar 13, 2012, 9:39:23 PM3/13/12
to coreplot...@googlegroups.com
Reply all
Reply to author
Forward
0 new messages