Learning Cocoa with Objective-C/Miscellaneous Topics/Printing

From WikiContent

< Learning Cocoa with Objective-C | Miscellaneous Topics
Revision as of 12:56, 7 March 2008 by Docbook2Wiki (Talk)
(diff) ←Older revision | Current revision (diff) | Newer revision→ (diff)
Jump to: navigation, search
Learning Cocoa with Objective-C

In the past, code to handle printing has been difficult to write. Many factors, such as margins, page orientation, and paper size, come into play. The differences in drawing models (between screen drawing and drawing to the printer) have made things even more challenging. Cocoa provides a clean printing interface that uses the same drawing model used to draw to the screen. In addition, just as Cocoa supports the use of calibrated color when drawing to the screen, ColorSync provides advanced color management when printing to paper.

As we saw in Chapter 7, when a view object receives a drawRect: message, it responds by drawing itself into the current graphics context. Usually, this context is a frame buffer, and the drawRect: message results in the view drawing its contents to the screen. The same machinery is used during printing, but the current graphics context is set to be the printer.

Remember (as discussed in Chapter 7) that the drawRect: method is never called directly to make a view appear on the screen; it is called only when the display message is sent to the view. The same methodology applies to printing; the drawRect: method is called when a print: message is sent to the view. Calling print: on a view causes the AppKit to display a print panel that asks the user which printer she wishes to use (along with page setup information). When the user clicks the Print button of the print panel, a sequence of drawRect: messages—one for each page—is sent to the view.

This chapter focuses on enabling basic printing from Cocoa applications. As with most things, once you have mastered the basics, you can make printing fairly complex—such as adding UI elements to the print panel and using alternate text views to reflow text—to satisfy special needs.


Printing a View

Since Cocoa makes it so easy to print a view, we're not going to waste any time. The following steps guide you through creating your first print job.

  1. Create a new Cocoa Application project in Project Builder (File → New Project → Application → Cocoa Application) named " View Print", and save it in your ~/LearningCocoafolder.
  2. Use the Finder to locate the Ripples Blue.jpgfile (/Library/Desktop Pictures), and drag it to the Resources group of your project.
  3. Open the MainMenu.nib file in Interface Builder. Click the Images tab on the MainMenu.nib window, and notice that the image we just added is present.
  4. Drag an Image View (NSImageView) from the Other Cocoa Views palette onto the main window, and then resize it to be larger, as shown in Figure 12-1.

    Figure 12-1. An Image View in the application window

    An Image View in the application window

  5. Drag the Ripples Blue image from the MainMenu.nib window to the Image View that we just added. When you drop the image onto the view, you should see the image appear there.
  6. Control-drag a connection from the File → Print menu item to the Image View. The inspector will pop up, if it's not already open, and indicate that the menu item is connected to FirstResponder.print:. Disconnect this connection, and connect the File → Print menu item to the print: action of the view, as shown in Figure 12-2. Be careful when dragging the connection, as it's easy to select the window as the target of the action.

    Figure 12-2. Creating a connection from the print menu item

    Creating a connection from the print menu item

  7. Save ([[Image:Learning Cocoa with Objective-C_I_1_tt472.png|]]-S) the nib file, and return to Project Builder.
  8. Build and run the project ([[Image:Learning Cocoa with Objective-C_I_1_tt473.png|]] -R).
  9. Select Print (File → Print, or [[Image:Learning Cocoa with Objective-C_I_1_tt474.png|]]-P) in the running application. The print dialog box will open, as shown in Figure 12-3.

    Figure 12-3. The print dialog panel in action

    The print dialog panel in action

  10. Click the Preview button. The application prints to a PDF file that will be displayed in the Preview application. Repeat the process, and click Print if you want to see the results printed on your printer.

Now that you have printed the view, notice that the entire image view drew itself onto the printer—border and all—and appears just as it did onscreen. If you just wanted to draw the image itself to the printer, you'd need to add a little code to control what gets printed. In the next section, we'll do just that with text.

Using Print Operations

Usually, you'll want more control over your printing than was available in our View Print application. This control is provided in Cocoa by creating print operations (instances of the NSPrintOperation class) and running them. You can think of a print operation as a controller object that mediates between the underlying print machinery of Mac OS X and the view being printed. Print operations use a helper object of type NSPrintInfo to help them determine how the page should be printed. If the print operation is constructed without a print info object, a default print info object for the application will be used.

We'll show you how to use print operations and print info objects in conjunction with printing using the document architecture, as covered in Chapter 10 and Chapter 11.

Printing Using the Document Architecture

To enable simple printing from a document-based application simply requires that a printShowingPrintPanel: method be implemented in the document class. This method is called by the document architecture on the active document when a user selects File → Print or presses [[Image:Learning Cocoa with Objective-C_I_1_tt476.png|]] -P.

To show this in action, we will create a simple editor that just prints the contents of the text document. So we can just focus on the printing-related code, we're going to create a new editor rather than using the one we just built. The following steps will guide you:

  1. Create a new Document-Based Application in Project Builder (File → New Project → Application → Cocoa Document-based Application) named "Document Print", and save it in your ~/LearningCocoafolder.
  2. Design the GUI by opening the MyDocument.nibfile in Interface Builder and performing the following steps:
    1. Remove the default text field.
    2. Drag an NSTextView from the Cocoa Data Views palette to the application's window.
    3. Resize the text view so that it occupies the entire window.
    4. Change the Autosizing options so that the view will follow changes in the window's size.
  3. In Project Builder, open MyDocument.h, and add a declaration as follows for the text view's outlet:
    #import <Cocoa/Cocoa.h>
    @interface MyDocument : NSDocument
        IBOutlet NSTextView * textView;
  4. Save (File → Save, or [[Image:Learning Cocoa with Objective-C_I_1_tt478.png|]] -S) MyDocument.h; then drag it onto Interface Builder's MyDocument.nib window so that Interface Builder can pick up the change to the file.
  5. Control-drag a connection from the File's Owner object (remember, this is a proxy for the MyDocument instance at runtime), and connect it to the textView outlet.
  6. Save (File → , or [[Image:Learning Cocoa with Objective-C_I_1_tt479.png|]]-S) the nib file.
  7. In Project Builder, open MyDocument.m and add the printShowingPrintPanel: method as shown here:
                            - (void)printShowingPrintPanel:(BOOL)flag
                                NSPrintInfo * printInfo = [self printInfo];                        // a
                                NSPrintOperation * printOp;                                        // b
                                printOp = [NSPrintOperation printOperationWithView:textView        // c
                                [printOp runOperation];                                            // d

    The code we added performs the following tasks:

    1. Obtains a reference to the printInfo object used by the document. This object is created automatically by Cocoa's document architecture for each document.
    2. Declares a printOp variable of type NSPrintOperation.
    3. Creates a new print operation that will print the contents of our text view using the print information that we obtained in line a.
    4. Calls the runOperation method on the print operation object. This puts the printing machinery into play.
  8. Save the project (File → Save, or [[Image:Learning Cocoa with Objective-C_I_1_tt481.png|]]-S).
  9. Build and run ([[Image:Learning Cocoa with Objective-C_I_1_tt482.png|]] -R) the application.
    1. Create some text and then print it (File → Print, or [[Image:Learning Cocoa with Objective-C_I_1_tt483.png|]]-P). A print dialog box will appear, as shown in Figure 12-4.
    2. Click either the Print button (to send the print job to your printer) or the Preview button (to send the print information to the Preview application, as shown in Figure 12-5). We recommend that you use the Preview button as you work through this chapter so that a few sheets of paper can be saved.

      Figure 12-4. Printing from a document-based application

      Printing from a document-based application

      Figure 12-5. Printed document in Preview.app

      Printed document in Preview.app

    3. Use the Page Setup (File → Page Setup, or Shift-[[Image:Learning Cocoa with Objective-C_I_1_tt486.png|]]-P) functionality to change the paper size and the orientation used.

Setting Margins

When printing text documents, we don't usually want the text centered on the page; we'd rather have it printed from the top-lefthand corner with some given margin.

  1. Modify our printShowingPanel: method as follows:
    - (void)printShowingPrintPanel:(BOOL)flag
        NSPrintInfo * printInfo = [self printInfo];
        NSPrintOperation * printOp;
        [printInfo setTopMargin:36.0];                                     // a
                             [printInfo setLeftMargin:36.0];                                    // b
                             [printInfo setHorizontallyCentered:NO];                            // c
                             [printInfo setVerticallyCentered:NO];                              // d
        printOp = [NSPrintOperation printOperationWithView:textView
        [printOp runOperation];

    The code we added performs the following tasks:

    1. Sets the top margin of the printed page to 36 points (1/2 inch). Points are a unit of measure used in page layout and typography, based on a scale of 72 points per inch. See Table 12-1 for a quick reference.

      Table 12-1. Points to inches conversion chart

      Point Size Measurement in Inches
      9 1/8
      18 1/4
      27 3/8
      36 1/2
      45 5/8
      54 3/4
      63 7/8
      72 1
    2. Sets the left margin of the printed page to 36 points.
    3. Indicates that the printed view should not be horizontally centered on the page.
    4. Indicates that the printed view should not be vertically centered on the page.

  2. Save the project (File → Save, or [[Image:Learning Cocoa with Objective-C_I_1_tt488.png|]]-S).
  3. Build and run ([[Image:Learning Cocoa with Objective-C_I_1_tt489.png|]]-R) the application. Now, when you print out a block of text, it will be printed starting at the upper-left corner, as shown in Figure 12-6.

    Figure 12-6. Printing at the top-left corner

    Printing at the top-left corner

Complete information on the settings for a print info object can be found in the /Developer/Documentation/Cocoa/TasksAndConcepts/ProgrammingTopics/Printing/index.html file installed on your hard drive with the Developer Tools.


  1. Add a Font menu to the application, and print out files with various fonts.
  2. Add printing to the Dot View application that we created in Chapter 8.
  3. Resize the image view in View Print to occupy the entire window (don't forget to set the Autosizing attributes!), and experiment with printing other images.
Personal tools