swiftpdfviewnsprintoperationnsprintinfonsprintpanel

Add 'PageSetupAccessory' to PrintPanel for PDFDocument


I have an app which displays a PDFView, and I want it to print the PDF file from the view. Also, I want the Print panel to show the Page Setup Accessory (i.e. the Paper Size, Orientation and Scale settings, like in Preview, which appear as one panel of the drop-down list of options).

Currently, I'm mistakenly printing the PDFView, not the PDF document itself. This only gives me one page and includes the scrollbars in the print-out! I can't see how to init an NSPrintOperation referencing a PDFDocument rather than the PDFView.

Here's my code, which works, but isn't what I want. I presume I'll have to override either the printDocument or printOperation functions of NSDocument with similar code that defines the Panel and the Info.

func thePrintInfo() -> NSPrintInfo {
    let thePrintInfo = NSPrintInfo()
    thePrintInfo.horizontalPagination = .automatic // Tried fit
    thePrintInfo.verticalPagination = .automatic // Tried fit
    thePrintInfo.isHorizontallyCentered = true // Tried false
    thePrintInfo.isVerticallyCentered = true // Tried false
    thePrintInfo.leftMargin = 0.0
    thePrintInfo.rightMargin = 0.0
    thePrintInfo.topMargin = 0.0
    thePrintInfo.bottomMargin = 0.0
    thePrintInfo.jobDisposition = .spool
    return thePrintInfo
}

// Need to show the 'Page Setup' Options as an Accessory
// e.g. Paper size, orientation.
@IBAction func printContent(_ sender: Any) {
    let printOperation = NSPrintOperation(view: thePDFView, printInfo: thePrintInfo())
    let printPanel = NSPrintPanel()
    printPanel.options = [
        NSPrintPanel.Options.showsCopies,
        NSPrintPanel.Options.showsPrintSelection,
        NSPrintPanel.Options.showsPageSetupAccessory,
        NSPrintPanel.Options.showsPreview
    ]
    printOperation.printPanel = printPanel
    printOperation.run()
}

Solution

  • Based on @Willeke's comments, I've come up with the following, which seems to work well. (Minor quibble is that the Print dialog isn't a sheet.) If anyone has any improvements, please post a better answer.

    @IBAction func printContent(_ sender: Any) {
       let printOperation = thePDFView.document?.printOperation(for: thePrintInfo(), scalingMode: .pageScaleNone, autoRotate: true)
    printOperation?.printPanel = thePrintPanel()
    printOperation?.run()
    }