Printing NSDocument

I am trying to print a document. The document is an array of NSImageReps or one NSPDFImageRep that has several pages. I find it difficult to understand how to use the NSPrintOperation class for printing.

NSPrintOperation seems to need NSView for printing. Do I need to manually add each image to the view in the calculated position, and then let it paginate? it doesn't seem like Cocoa ... is there some kind of technique that I am missing?

+4
source share
4 answers

In the future, I believe the answer is PDFViews. you can immediately add PDFPage to PDFView (via PDFDocument), and then you can print using printWithInfo: autoRotate:

In theory, at least I got the view created, and the print dialog appears, but when I press "print", the dialog does not disappear ...

But that is another question.

0
source

You cannot print what is impossible to draw. NSView is how you draw what you want to print. You can subclass NSView just for printing, which decides how you want the print to work (for example, you need one NSImageRep page for a page — ANY page size?) Using NSView pagination methods. Just override knowsPageRange: to return YES.

+1
source

You can create a view that displays what you want to print. Then you use it to create a print operation. A.

Usually you created a view displaying your image. You implement an algorithm to determine which image you want to display on which page. Then you return the number of pages available for printing and implement the method for printing a specific page.

  • If you have 10 images and want to print on the page, which is easy.
  • If you want to print records on a page and you have 100 records, then you calculate how many records you can fit on a page (using the current font size and the number of lines per record).
  • Then you determine from the records per page how many pages you need to show all the records - this is your number of pages (page range).
  • When you request to print a specific range of pages on which you select the entries to be displayed on this page and show them.
  • See the links below on how to complete these steps. See custom pagination for an example of how to implement these steps, it is not difficult.

See Printing Programming Topics , or the full example that I refer to below has pagination that I have not included here. See your custom pagination for more tips.

If you have a document-based application and a view that you want to dump to the printer, then in our MyDocument (or whatever you call it) that extends NSDocument , you must implement:

 - (NSPrintOperation *)printOperationWithSettings:(NSDictionary *)ps error:(NSError **)e 

The view then uses the standard drawRect: for drawing.

For example, here PeopleView simply draws the details of the people table , here NSDictonary people employees :

 - (NSPrintOperation *)printOperationWithSettings:(NSDictionary *)ps error:(NSError **)e { PeopleView * view = [[PeopleView alloc] initWithPeople:employees]; NSPrintInfo * printInfo = [self printInfo]; NSPrintOperation * printOp = [NSPrintOperation printOperationWithView:view printInfo:printInfo]; [view release]; return printOp; } 

For more information, see Chapter 27, Printing, in Hillegass Cocoa for Mac OS X.

+1
source

Despite the accepted answer, in fact it does not answer the main question, it just gives a workaround.

I had a similar problem (I have an array of objects, each of which is displayed by the same NSView subclass, one per page). This is how I solved it, without the baroque nonsense of creating one gigantic view containing all the pages ...

1) We have a subclass of NSView that has a model associated with it ( NSImage in your case, ModelData in my case)

 class BaseView: NSView { var modelData: ModelData /* Whatever your view needs to draw */ //... } 

2) Your document controller has an array of var models: [ModelData] .

3) Create a new subclass that will be displayed on the printer.

 class PrinterView: BaseView { var pageIndex: Int = 1 var modelArray: [ModelData] init(frame: NSRect, models: [ModelData]) { self.modelArray = models super.init(frame: frame) } required init?(coder: NSCoder) { fatalError("invalid initializer") } override func knowsPageRange(_ range: NSRangePointer) -> Bool { range.pointee.location = 1 range.pointee.length = self.modelArray.count return true } override func rectForPage(_ page: Int) -> NSRect { self.pageIndex = page return self.bounds } override func draw(_ dirtyRect: NSRect) { self.model = self.modelArray[self.page - 1] // Pages are 1, not 0, based super.draw(dirtyRect) } } // That it! That all... 

4) Do this in your document controller:

 override func printOperation(withSettings printSettings: [String : Any]) throws -> NSPrintOperation { self.printInfo.horizontalPagination = .fitPagination self.printInfo.verticalPagination = .clipPagination let printView = PrinterView(size: self.printInfo.paperSize, models: self.models) return NSPrintOperation(view: printView, printInfo: self.printInfo) } 
+1
source

Source: https://habr.com/ru/post/1304495/


All Articles