Chapter 20. Pasteboards, Services, Modal Sessions, and Drag-and-Drop

In the previous chapter, we showed how images produced by the GraphPaper application can be incorporated into other programs by saving the images in PDF or TIFF files. In this chapter, we’ll show more ways that Cocoa provides for making applications work together: the cut, copy, and paste system; the Services system; and the drag-and-drop system. To make the Services system work, we’ll also need to introduce the concept of modal sessions — that is, event loops other than the primary event loop. You’ll enjoy this chapter, because Services and drag-and-drop are really nifty features.

Cut, Copy, and Paste with the Pasteboard

The Cocoa NSPasteboard object provides a simple and direct way for users to transfer data between applications using familiar copy, cut, and paste commands. In fact, every application we’ve created already implements copy, cut, and paste inside the text fields: this behavior is built into the NSTextView class.

Cocoa extends the traditional notions of cut, copy, and paste by providing multiple pasteboards (clipboards), each of which can hold several different data representations simultaneously. It also provides lazy evaluation , a system whereby information is not put onto the pasteboard unless it is needed by a receiving application.

Types of Pasteboards

Cocoa provides the following five basic pasteboards:

General pasteboard (NSGeneralPboard)

Used to cut, copy, and paste data between applications. This pasteboard supports the ordinary Cut, Copy, and Paste menu commands. (It was formerly called the NSSelectionPboard, because it’s the pasteboard used for selections.)

Ruler pasteboard (NSRulerPboard)

Holds information about margins and tab stops. This pasteboard supports Copy Ruler and Paste Ruler commands such as those often found in word processor applications.

Font pasteboard (NSFontPboard)

Holds information about character font size, format, and style. This pasteboard supports Copy Font and Paste Font menu commands.

Find pasteboard (NSFindPboard)

Holds information about the current state of each application’s Find panel. Although most applications don’t use the Find pasteboard, it is designed so that you can execute a Find command in one application and then execute a Find-Next command in another application without having to retype the search string.

Drag pasteboard (NSDragPboard)

Holds information when objects (such as color chips) are dragged from one window (or application) to another.

You can also create your own pasteboards and use them between different applications that you write. Of course, other people’s applications are not likely to know of their existence.

Users and Pasteboards

Pasteboards are generally transparent to the user. That is, users don’t realize that there are five distinct pasteboards — they simply benefit from the fact that, for example, cutting text from one application and pasting it into another doesn’t change the last ruler that they copied or pasted. Likewise, a user might search for the word “Cocoa” in one application, not find it, switch to another application and type Command-F again, and then be pleased to discover that the “default” search string is still “Cocoa” (because the string was put onto the NSFindPboard by the first application and then read from there by the second one). Users are also generally unaware that Cocoa pasteboards can hold data in multiple representations at the same time — they simply like the results when they paste from one application into another.

Consider this: if you create a complex image with Stone’s Create program, copy it to the pasteboard, switch to TextEdit, and then choose the Paste command, TextEdit may paste the image into the window in PDF, TIFF, and possibly a number of other formats. If you quit Create and then start it up again and paste the image from the pasteboard into the new Create document, you will actually paste in a fully editable Create document, rather than just an image. This is because Create puts several different kinds of representations of the copied illustration onto the pasteboard, including the PDF and TIFF formats, which other programs can use, and Create’s internal file format.

There’s also nothing like the pasteboard for showing bugs and implementation errors in Cocoa applications. For example, if you copy an image from Create and paste it into OmniGraffle, you’ll discover that OmniGraffle pastes in the TIFF representation, even though the PDF representation is also on the pasteboard. Paste in a tiny star and then stretch it to make it big, and you’ll see lots of pixelation and jaggies. Likewise, if you make an illustration in OmniGraffle and paste it into Create, you’ll see that it gets pasted in as a TIFF, not as a PDF. It turns out that both of these are the same bug, a bug in the NSImage implementation that is part of the Mac OS X Version 10.1 operating system. NSImage in Version 10.1 always returns a TIFF image, even if only a PDF file is located on the pasteboard.

Unfortunately, when you find one of these bugs, all you can do is report it to the program’s author and go on: the pasteboard system doesn’t give you a way to fix bugs in other people’s programs (Andrew Stone at Stone Design fixed that bug in Create just a few hours after it was reported, by coding around the bug in the NSImage class).

Providing Data to the Pasteboard

Cocoa keeps data on the pasteboard using a separate program called pbs, or the pasteboard server. (Use the ProcessViewer utility application or enter the Unix command ps aux in a shell window to see the running pbs server.) You can communicate with the pasteboard server only indirectly, by sending messages to the NSPasteboard object.

There are seven commonly used NSPasteboard methods. The following two class methods return the id of an NSPasteboard object:

+ (NSPasteboard *)generalPasteboard

Returns the id of the general pasteboard

+ (NSPasteboard *)pasteboardWithName:(NSString *)name

Returns the id of a pasteboard with a given name.

The following two instance methods put data onto a pasteboard. They are usually invoked by thecut: or copy: methods that handle the Cut or Copy menu commands (or by your overrides of these methods).

- (int)declareTypes:(NSArray *)newTypes owner:(id)newOwner

Tells the pasteboard which types you can provide

- (BOOL)setData:(NSData *)data forType:(NSString *)dataType

Writes the data for a particular type to the pasteboard

The following instance methods take data from the pasteboard. These are usually invoked by a paste: method that handles the Paste menu command.

- (NSArray *)types

Returns an array listing the kinds of types available for pasting

- (NSString *)availableTypeFromArray:(NSArray *)types

Scans the array of types and returns the first type on the pasteboard that matches one of the types in the array

- (NSData *)dataForType:(NSString *)dataType

Reads data of the specified type from the pasteboard server; returns nil if the type is not available

Cocoa defines 15 basic pasteboard data types, as shown in Table 20-1.

Table 20-1. Cocoa pasteboard types

Type

Contents

NSColorPboardType

NSColor data

NSFileContentsPboardType

A representation of a file’s contents

NSFilenamesPboardType

An NSString designating one or more filenames

NSFontPboardType

Font and character information

NSHTMLPboardType

HTML (which NSTextView can read from, but not write to)

NSPDFPboardType

PDF data

NSPICTPboardType

QuickDraw Picture data

NSPostScriptPboardType

Encapsulated PostScript (EPS) code

NSRulerPboardType

Paragraph formatting information

NSRTFPboardType

Rich Text Format (RTF)

NSRTFDPboardType

RTFD-formatted file contents

NSStringPboardType

NSString data

NSTabularTextPboardType

An NSString containing tab-separated fields of text

NSTIFFPboardType

Tagged Image File Format (TIFF)

NSURLPboardType

NSURL data

Data on the pasteboard is stored as an array of bytes, in a way similar to the way that you might store it in a file, but you’ll always get the contents of the pasteboard in an NSData or an NSString object.

Programs can put data on the pasteboard in two ways:

Immediately

For example, when the user types Command-C, the program puts all of the selected data on the pasteboard.

Lazily

When the user presses Command-C, the program simply tells the pasteboard what kinds of data it could provide if asked. Then, when the user does a paste in another application, the program that originally copied the data onto the pasteboard is asked to provide the requested data.

Most Cocoa programs write one format onto the pasteboard when the user performs a cut or copy operation and use lazy evaluation to provide the other kinds of representations that the application knows about. The representation written first should be the most “rich” representation of the data possible — a representation that can be used to reconstruct all the others. If the application performing the paste operation wants data in a different format, the first application reads the richest description from the pasteboard, converts the data to the requested format, and writes it back.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.217.251.56