Programming Guide: Clipboard Transfer

# Programming Guide

## Clipboard Transfer

The clipboard commands Cut, Copy, and Paste constitute a common mechanism for transferring data within and across conventional documents, even documents of different data formats. For OpenDoc documents, these commands perform the same tasks, but with added capabilities:

- The commands operate on embedded parts as well as intrinsic content. The data copied to or pasted from the clipboard can contain any number of parts, of any part kinds. The parts may be displayed in frames or represented as icons.

- The Paste and Paste As commands can either embed parts or incorporate data as intrinsic content.

- The Paste and Paste As commands can cause a portion of one part's intrinsic content to become, when copied and then pasted into another part, a separate, embedded part on its own.

- The Paste As command can create a persistent link to the source of the data being pasted.

- The Paste As command also allows the user to override decisions on incorporating versus embedding that would normally be made by OpenDoc.

Similar to data in a conventional clipboard, if your part editor stores multiple formats on the clipboard, including standard formats, the user has a greater chance of incorporating, rather than embedding, the data into more kinds of parts.

### Clipboard Concepts

These concepts are some basic clipboard operations common to reading and writing. These concepts include acquiring the clipboard focus, using the clipboard update ID, and special considerations related to updating the clipboard and cutting data from your part.

#### Enabling the Cut and Paste Menu Items

OpenDoc does not permit changes to your draft (and therefore your part's content) if the draft permissions are read-only. You should check your draft permissions (see "Drafts") before enabling the Cut, Paste, or Paste As items in the Edit menu and before allowing the user to perform a cut or paste operation using keyboard equivalents.

The CanEmbed method can help parts determine whether or not they should enable the Paste menu items. The CanEmbed method queries the registration manager for a part editor capable of handling the content of the clipboard storage unit. It is intended for use by the container parts.

#### Acquiring and Relinquishing the Clipboard Focus

To be thread-safe, you must always acquire the clipboard focus before writing or reading clipboard data. As long as you hold the clipboard focus, no other part can access or modify the data.

Typically, your part needs to inspect the contents of the clipboard before deciding whether to enable Edit menu items, so your AdjustMenus method can include a call to the arbitrator's RequestFocus method to acquire the clipboard focus.

After acquiring the clipboard focus, you can access the clipboard when responding to a menu command (or its keyboard equivalent) with your HandleEvent method by calling the session object's GetClipboard method. You should then unilaterally relinquish the clipboard focus in your HandleEvent method, after having handled the clipboard command. (Your HandleEvent method is always called after AdjustMenus is called, even if the user does not choose a menu command.)

These are the steps you take to acquire the clipboard focus and prepare to write to it or read from it:

1. Acquire the clipboard focus, using the Arbitrator's RequestFocus method (as described in "Requesting Focuses").

2. Get access to the clipboard object, using the session object's GetClipboard method.

3. If you are writing to the clipboard, remove any existing data on the clipboard with the clipboard's Clear method. (Do not take this step if you are reading from the clipboard.)

4. Get access to the clipboard's content storage unit, using the clipboard's GetContentStorageUnit method.

You relinquish the Clipboard focus by calling the arbitrator's RelinquishFocus method.

#### Clipboard Update ID

Whenever you copy data to the clipboard, you should get and save the clipboard's current update ID, a number used to identify this particular instance of clipboard contents. You typically obtain the update ID in this situation by calling the clipboard's ActionDone method. In other situations, you may need to inspect the clipboard's current update ID; you can do so by calling the clipboard's GetUpdateID method.

If a link specification that you have written to the clipboard becomes invalid because of changes to your content that was copied to the clipboard, you must remove the link specification from the clipboard, as described in "Removing a Link Specification from the Clipboard". You can examine the clipboard's current update ID at any time and compare it with your saved update ID; if they are identical, the clipboard has not changed.

#### Removing a Link Specification from the Clipboard

If your part copies some of its content to the clipboard and the user then modifies the equivalent content in your part (without copying anything else to the clipboard), the clipboard data no longer exactly matches the source data in your part. The potential link represented by the link specification you wrote in the clipboard therefore no longer reflects the content at the source of the link. If your source content has changed to the extent that creating a link is no longer feasible, your part must remove the link specification.

By saving the update ID of the clipboard whenever you copy data to it, you can check that ID against the current update ID of the clipboard whenever your source data changes to the extent that creating a link to the previous data is impossible. If the IDs match, the clipboard still contains the data that you placed in it, and you should remove the link specification.

You can follow these steps to remove a link specification:

1. Acquire the clipboard focus as described in "Acquiring and Relinquishing the Clipboard Focus".

2. Get the clipboard's update ID and compare it to your stored update ID. If they do not match, skip to step 5.

3. Access the clipboard's content storage unit. (Unlike when writing to the clipboard, do not clear the clipboard data.)

4. Focus the storage unit on the link-specification property (type kODLinkSpec), and remove that property, using the storage unit's Remove method. Be sure to focus on the entire property (by specifying a null value type), so that you remove the entire property, not just one value.

5. Call the clipboard object's ExportClipboard method.

6. Relinquish the clipboard focus.

#### Undo for Clipboard

If your part supports cutting, copying, or pasting, it must also support undoing those operations. Data transfer between parts is undoable only if both parts have undo support. Undo support in general is described in "Undo".

Whenever your part performs a cut, copy, or paste operation, it must call the clipboard's ActionDone method, to notify the clipboard of the kind of cloning transaction that took place. ActionDone returns a clipboard ID that identifies the current clipboard contents. Save that update ID.

When your part cuts an object to the clipboard, it should remove the object from its content data structures. However, your part should not release the object, but instead save a reference to the object in an undo action. (For a cut embedded frame, you also set its in-limbo flag to true, as shown in Table 5. Then, if the user chooses the Undo command and your part's UndoAction method is called, your part should:

- Reinstate the object in your part's content structures (and setting its in-limbo flag to false).

- Notify the clipboard that the cut was undone, by calling the clipboard's ActionUndone method, passing it the update ID returned to you when you called ActionDone after cutting the data to the clipboard. If the user subsequently chooses the Redo command and your part's RedoAction method is called, your part should

- Once again remove the object from its content data structures (and reset its in-limbo flag to true)

- Notify the clipboard that the cut was redone, by calling the clipboard's ActionRedone method, passing it the same update ID

Calling ActionDone, ActionUndone, and ActionRedone notifies the clipboard whether it is involved in a cut, a copy, or the restoration of a cut or a copy; the clipboard's internal handling of its objects differs in each case.

If and when your part's DisposeActionState method is called, you can at that point release (not remove from your draft) the object referenced in your undo action. (For an embedded frame, you either release or remove it, as shown in Table 5.)

To undo a cut, copy, or paste operation requires the restoration of the previous state of the document involved, but it does not require the restoration of the previous state of the clipboard. Therefore, if you redo a paste operation that has been undone, you cannot assume that the clipboard once again contains the original data that had been pasted. You must implement the redo from your own data. For this reason, you should retain a copy of pasted data in a private cache.

### Copying or Cutting to the Clipboard

You write data to the clipboard as a result of the user selecting the Cut command or the Copy command from the Edit menu (or their keyboard equivalents). These are the basic steps to take:

1. Acquire the clipboard focus and access the clipboard's content storage unit, as described in "Acquiring and Relinquishing the Clipboard Focus".

2. Write the data to the clipboard.

   - If the selection consists of a combination of your part's intrinsic content plus zero or more embedded parts, you need to write your own intrinsic content to the clipboard, and you need to clone the embedded frames and parts as well (or you can write a promise). Follow the steps listed in "Writing Intrinsic Content".

   - If the selection consists of a single frame of an embedded part, with no surrounding intrinsic content, you need to clone the part and provide a frame for it. Follow the steps listed in "Writing a Single Embedded Frame".

   In either case, when you call the BeginClone method, specify either kODCloneCopy or kODCloneCut, depending on whether you are copying or cutting the data to the clipboard.

3. When you have finished, call the clipboard's ActionDone method, specifying either kODCloneCopy or kODCloneCut. Save the clipboard's current update ID (see "Clipboard Update ID"), which is returned from ActionUndone, in case you later have to undo the cut or copy, remove a link specification, or fulfill a promise you wrote.

4. If this operation was a cut rather than a copy, it must be undoable. Add a single action to the action history, as described in "Adding an Action to the Undo History". Be sure to follow the special instructions in "Handling Cut Data", including setting the in-limbo flag of any cut frame to true.

5. Delete the cut selection from your part's content.

6. Call the clipboard object's ExportClipboard method.

7. Relinquish the clipboard focus (see "Acquiring and Relinquishing the Clipboard Focus").

### Pasting from the Clipboard

You read data from the clipboard as a result of the user selecting the Paste command or the Paste As command from the Edit menu. These are the basic steps to take:

1. Acquire the clipboard focus and access the clipboard's content storage unit, as described in "Acquiring and Relinquishing the Clipboard Focus". (Do not clear the clipboard data, of course).

2. Read the data from the clipboard.

   - If the data consists of intrinsic content plus zero or more embedded frames, and if the intrinsic content is of a part kind that you can incorporate into your part, you need to read the intrinsic content and possibly clone embedded parts, links, or other objects. Follow the steps listed in "Incorporating Intrinsic Content".

   - If you need to embed the data as a single part with no surrounding intrinsic content, you need to clone the part and either extract its frame or create a frame for it. Follow the steps listed in "Embedding a Single Part". That section lists the conditions under which you must embed rather than incorporate clipboard data.

   In either case, when you call the BeginClone method, specify kODClonePaste.

3. Pasting must be an undoable operation. Call the clipboard's ActionDone method, specifying kODClonePaste. Save the current clipboard update ID, returned by ActionDone, in a single undo action (see "Adding an Action to the Undo History", so that you can undo the paste operation if necessary. If you are pasting an embedded frame, follow the instructions listed in Table 5. Save the current value of the frame's in-limbo flag and then set the flag to false.

4. Notify OpenDoc and your containing part that there has been a change to your part's content; see "Making Content Changes Known".

5. Relinquish the clipboard focus (see "Acquiring and Relinquishing the Clipboard Focus").

[ Top | Previous | Next | Contents | Index | Documentation Homepage ]