Programming Guide


Storage Issues for Data Transfer

This section introduces some of the storage-related concepts used in clipboard transfer, drag and drop, and linking, which are described in detail later in this chapter.

For the purposes of this section, the term data-transfer object means any of the following: the clipboard or drag and drop object (when reading or writing data), a link-source object (when writing linked data), or a link object (when reading linked data).

Data Configuration

When a part places data on the clipboard or other data-transfer object, it writes a portion or all of its intrinsic content to the data-transfer object, and it also can cause the contents of one or more embedded parts to be written.

Whatever the nature of the data, once it is written to the data-transfer object it can be considered an independent part. It has its own intrinsic content and it may contain embedded parts. In writing or reading the data, your part is directly concerned only with the characteristics (such as part kind) of the intrinsic content of the transferred part. All embedded parts are transferred unchanged, as embedded parts, during the process.

The storage unit for the data-transfer object's intrinsic content is called its content storage unit. It is the main storage unit for the content of the data-transfer object, equivalent to a part's main storage unit (see "Main and Auxiliary Storage Units"). Any embedded parts in the transferred data, and any other OpenDoc objects, have their own storage units.

Note:

A link object or a link-source object is a persistent object, and as such has its own main storage unit. That storage unit is not the same as its content storage unit. Always access the content of a data-transfer object by calling its GetContentStorageUnit method.    
More specifically, the data-transfer object's intrinsic content is stored in the contents property (type kODPropContents) of the content storage unit. When writing to a data-transfer object, your part can store data in multiple formats in different values of the contents property. Just as with a part, each value in the contents property must be complete; it must not depend on other properties or other values of the property.

Your part accesses other properties besides the contents property in a data-transfer object. For example, when your part writes data to a data-transfer object, it may also write, into a separate property, a frame object or a frame shape for the destination part to use when constructing a display frame. See "Annotations" for more information.

Objects in memory take precedence over their stored versions in data transfer. If the user cuts or copies a part's frame to the clipboard or other data-transfer object, the moved data represents the current state of the part, including any edits that have not yet been saved to disk.

Annotations

This section discusses the items, in addition to part content, that you can write to or read from the storage unit of a data-transfer object.

Link Specification

When copying content to the clipboard or drag and drop object, a part advertises the ability to create a link by writing a link specification in addition to content. When you copy data to the clipboard or drag and drop object, you should create a link specification, using your draft's CreateLinkSpec method, if the user chooses to link to the data when pasting or dropping it in the destination.     "Writing Intrinsic Content" illustrates when to write a link specification.

You should write the link specification onto the content storage unit of the clipboard or drag and drop object as a property with the name kODPropLinkSpec. The data in a link specification is private to the part writing it. The data you place in your link specification is returned to your part if and when your part's CreateLink method is called to create the link. All that your part needs from the link specification data is sufficient information to identify the selected content.

Because the link specification is valid only for the duration of the current instantiation of your part, the link specification can contain pointers to information that you maintain.

Link specifications are not necessary in the following situations:

When you write a link specification to the clipboard, obtain and save the clipboard update ID (see "Clipboard Update ID"). You must remove a link specification from the clipboard if your source data changes so that the clipboard data no longer reflects it, and you need the update ID to test for that situation. See "Removing a Link Specification from the Clipboard".

You never need to remove a link specification from the drag and drop object, because it is valid only during the course of a single drag operation.

Note:

The kODPropLinkSpec property is not copied when the storage unit containing it is cloned.

Frame Shape or Frame Annotation

When you place intrinsic content (with or without embedded frames) on the clipboard or other data-transfer object, there is no frame associated with that content.   You should, nevertheless, write a frame shape to the data-transfer object to accompany the content; the shape is a suggestion to any part that reads the data and must embed it as a separate part. You write the frame shape into a property named kODPropSuggestedFrameShape in the data-transfer object's content storage unit.

Likewise, if your part receives a paste or drop from the data-transfer object and embeds the instrinsic data, your part should examine the kODPropSuggestedFrameShape property to get the source part's suggested frame shape for the data. If the kODPropFrameShape property does not exist, use your own part-specific default shape.

If you place one of your embedded parts (in the form of a single embedded frame) on the clipboard or other data-transfer object, you must place the frame object there also. You write the frame into a property with the name kODPropContentFrame in a storage unit of the data-transfer object's draft.

Likewise, if your part receives a paste or drop from the data-transfer object, you can note from the presence of the kODPropContentFrame property that the data represents a single frame that should be embedded, and you can retrieve the frame from the property.

When you transfer a single embedded frame, you can specify the frame location relative to your part's content (that is, the offset specified in the external transform of the frame's facet) by incorporating the offset into the frame shape that you write. Then, the receiving part of the paste or drop can, if appropriate to its content model, use that offset to construct an external transform.

Note:

Neither the kODPropSuggestedFrameShape nor kODPropContentFrame property is copied when the storage unit containing it is cloned.

Proxy Content

When you write a single embedded frame to a data-transfer object, you can optionally write any intrinsic data that you want to associate with the frame. The intrinsic data might be a drop shadow or other visual adornment for the frame, or it might be information needed to reconstruct the frame as a link source or link destination.

This information is called proxy content; to write it, you add a the kODPropProxyContents property to the data-transfer object, and write your data into it as a value that your part recognizes. If the transferred part is subsequently embedded into a part that also recognizes that value and knows how to interpret it, the added frame characteristics can be duplicated.

If your part receives a paste or drop and embeds the single part, that proxy content for that frame exists. The proxy content exists due to the presence of the kODPropPrxoyContents property. If your part understands the format of the proxy content, you can read it and duplicate the frame characteristics. To determine if you frame understand the proxy content format, examine the value types in the property.

Note:

The kODPropProxyContents property is not copied when the storage unit containing it is cloned.

Cloning-Kind Annotation

When a single embedded part is written to a data-transfer object, its containing part writes a property with the name kODPropCloneKindUsed to the data-transfer object. The property specifies the kind of cloning transaction used to clone the embedded part. If the embedded part writes a promise instead of actual data to the data-transfer object, it uses the information in the kODPropCloneKindUsed property when it later fulfills the promise.

For more information, see "Fulfilling a Promise".

Mouse-Down Offset Annotation

If your part initiates a drag operation (see "Initiating a Drag"), you need to create a property named kODPropMouseDownOffset in the drag and drop object's storage unit. Write into that property a value that specifies the location of the mouse-down event that triggered the drag. The value should be of type ODPoint and should contain the offset from the origin of the content being dragged.

If your part receives a drop, it should likewise check for the presence of the kODPropMouseDownOffset property. If the property exists, and if taking it into account is consistent with your part's content model, use it to locate the dropped content in relation to the mouse-up event that marks the drop.

Note:

The kODPropMouseDownOffset property is not copied when the storage unit containing it is cloned.

Drag and Drop Annotations (For OS/2)

Each content storage unit of the drag and drop object contains a PM DRAGITEM structure corresponding to a drag item in the current drag and drop operation. It is written by the drag and drop object under the kODDragitem value of the kODPropContents property. Usually parts don't have to interact with this value other than in their Drop method, when they have to create a storage unit view for it and pass it to the GetDataFromDragManager method of the drag and drop object to perform data rendering.

The drag and drop object supports data rendering for two mechanisms: DRM_SHAREDMEM and DRM_OS2FILE. If either one of these mechanisms has been selected (RMF selection is done by calling drag and drop CanEmbed or CanIncorporate methods from within the part's DragEnter method), the storage unit rendered by GetDataFromDragManager will contain the rendered data with no kODDragitem value. If the selected rendering mechanism is DRM_OS2FILE and this is not an OPENDOC initiated drag, the rendered storage unit will contain the following values for its kODPropContents property:

Selected kind

Part kind that the selected RMF was mapped to; no value is set for this kind. The actual data has to be read from the dropped file.

kODFileType

Name of the dropped file; value type is ODISOStr.

kODFileTypeEA

Any extended attributes that are associated with the file; value type is ODISOStr.

If the selected rendering mechanism is not handled by the drag and drop object, the target part has to perform the data rendering. In this case, the kODPropContents in the storage unit rendered by GetDataFromDragManager will contain a set of values necessary for the part to carry out the rendering conversation:

kODDragitem

DRAGITEM structure; value type is DRAGITEM.

kODSelectedRMF

Selected rendering mechanism and format pair; value type is ODISOStr.

kODSelectedKind

Part kind that the selected RMF was mapped to; value type is ODISOStr.

kODDragOperation

PM drag operation from the DRAGINFO structure associated with this drag; value type is ODUShort.

Clonable Data Annotation Prefix

In some situations an entity may need to store properties in the storage unit of a part or other object without the knowledge or cooperation of the part itself. For example, a service such as a spell checker might store a dictionary of exceptions as a property of a part's storage unit. The part is unaware of the existence of that property, but the spell checker would want the dictionary cloned whenever the part is cloned.

When a storage unit itself is cloned (see "Cloning"), all its properties are copied, no matter who wrote them into the storage unit. However, the in-memory version of an object is given preference over its storage unit during cloning, because recent, unsaved changes to the object should be included in the cloning operation. Unfortunately, when an in-memory object clones itself, any of its properties that the object itself is unaware of are not cloned, because it does not know to write them into the destination storage unit.

To support this capability, OpenDoc defines the property prefix constant kODPropPreAnnotation, whose value is OpenDoc:Annotation:. When that prefix is part of a property name (for example, OpenDoc:Annotation:Exceptions) in an object's storage unit, OpenDoc always copies that property when the object is cloned, even if the object being cloned is in memory and regardless of whether the object is aware of the existence of the property.

Therefore, if your part stores data in another object that the object itself does not use but that you want to be cloned along with the object, make sure you store it in a property whose name starts with the string defined by kODPropPreAnnotation.

Cloning

You should always transfer data to and from the clipboard or other data-transfer object in the context of cloning. This section describes how cloning works, what the scope of a cloning operation is, and how to implement your part editor's CloneInto method.

Cloning an object is copying that objec, all objects it references, and all objects they in turn reference. Copies are made of all storage units or their equivalent proxies that are references with strong persistent references. Storage units referenced with weak persistent references are not copied. For more information on how strong and weak persistent references affect cloning, see "Persistent References" and Figure 60.

Actually, each object cloned during the operation decides, if it is in memory, which of its storage-unit's properties and which of its referenced objects should be included. If the object is not currently instantiated, all of its storage unit's properties and all of its strongly referenced objects are copied.

Cloning Sequence

All persistent objects have a CloneInto method by which they clone themselves, but your part editor should not call the CloneInto method of any object directly. Instead, you clone an object by calling the Clone (or WeakClone) method of its draft object. The Clone method in turn calls the CloneInto method of the object involved. (Your parts, as persistent objects, must provide a CloneInto method. See "CloneInto Method of Your Part Editor" for more information.)

Cloning is a multistep transaction, designed so that it can be terminated cleanly if it fails at any point. You perform a clone by calling three methods, in this order:

BeginClone

First, call the BeginClone method of the draft object of the data to be cloned. If you are transferring data from your part, call your part's draft object; if you are transferring data from a data-transfer object, call that object's draft object. BeginClone sets up the cloning transaction.

(If you are cloning as a result of pasting or dropping data into your part, you must also specify the destination frame, the display frame of your part that is receiving the paste or drop.)

When you call BeginClone, you are returned a draft key, a number that identifies that specific cloning transaction. You pass that key to the other cloning methods that you call during the transaction. You also specify in the kind parameter to the BeginClone method the kind of cloning operation that is to be performed, so that OpenDoc can maintain the proper behavior for linked data that is being transferred. Table 9 lists the kinds of cloning transactions that OpenDoc recognizes.

Table 9. Kinds of Cloning Operations
kind parameter Meaning
kODCloneCopy Copy object from source to data-transfer object
kODCloneCut Cut object from source to data-transfer object
kODClonePaste Paste object from data-transfer object to destination
kODCloneDropCopy Copy object to the destination of a drop
kODCloneDropMove Move object to the destination of a drop
kODCloneToLink Copy object from source to update a link source
kODCloneFromLink Copy object from link to update a destination
kODCloneAll Clone all objects (your part should not use this)

Even when transferring only intrinsic content (and not actually cloning any objects), you should still bracket your transfer with calls to BeginClone and EndClone. That way, you notify OpenDoc of the kind of operation (such as cut or copy) that is being performed and you ensure that the right actions occur at both the source and destination of the transfer.

Clone

For each object that you are cloning, call the draft's Clone method. Clone allows the draft object to specify and recursively locate all objects that are to be cloned. It calls the CloneInto method of the object to be copied, which results in calls to the CloneInto methods of all referenced objects, and so on. For example, when Clone calls the CloneInto method of a part, the part clones its embedded frames; the embedded frames, in turn, clone the parts they display, and so on.

(You sometimes call the draft's WeakClone method instead of Clone, especially when you are cloning within the context of your own CloneInto method. See "CloneInto Method of Your Part Editor" for more information.)

Take these steps when calling the Clone method:

  1. First, obtain an object ID to pass to Clone.

  2. Pass the object ID to the Clone method.

  3. Save the resultant object ID that Clone returns, along with the IDs returned from other calls to Clone, until cloning is complete and you have called EndClone (See "EndClone").

    (If you are not actually cloning objects but simply reading or writing intrinsic data, this is the point at which to read or write, instead of calling Clone.)

In cloning, the in-memory version of an object takes precedence over its stored version. For this reason, an object does not need to be written to storage prior to being cloned. If the object is in memory, its CloneInto method is called to perform the clone; if the object is not in memory, its storage unit performs the clone operation.

This convention also means that, if an object is in memory, properties attached to its storage unit that the object itself does not know about might not be copied, unless they are specially named; see "Clonable Data Annotation Prefix" for an explanation.

Null IDs when cloning links

The Clone method returns a value of kODNullID if the desired object cannot be cloned. For example, Clone does not allow you to clone a link object or link-source object into a link, and it returns kODNullID if you attempt to do so. In this case, because you cannot clone the object, you should delete any data associated with it that you have written into the data-transfer object. However, in the case of a link or link source you should still write the content formerly associated with the object, but as unlinked content.

Annotation properties not cloned

When data is cloned from a data-transfer object, most of the annotation properties (such as kODPropLinkSpec) that the source part may have added to the content storage unit are not transferred, because they make no sense as properties outside of the data-transfer object. If you clone a storage unit from a data-transfer object and need these properties, you must read them from the data-transfer object's storage unit, not from the cloned storage unit.

EndClone

Finally, call the draft's EndClone method. EndClone commits to and actually performs the cloning operation. After EndClone completes, you can then use or reconnect the cloned objects.

  1. Pass each returned object ID that you have saved to your draft's IsValidID method to determine if the object was cloned.

  2. If IsValidID returns true, you can at this point reconstruct either the cloned object in memory or a persistent reference to it:

  3. If IsValidID returns false, the object was not cloned and you should exclude it from the data you are reading or writing.

    If, at any time after calling BeginClone, the operation cannot be completed, you can terminate the transaction by calling the AbortClone method instead of EndClone.

Note:

You cannot instantiate and use any cloned object until after the entire cloning operation is complete. If you are cloning several parts and link objects, for example, you cannot call AcquirePart or AcquireLink until after you have cloned all of the objects and EndClone has successfully returned.

Scope of a Clone Operation

For cloning, the scope defines the set of objects that are to be included in the cloning operation. Scope is expressed in terms of a frame object or its storage unit.

Because a part can have more than one display frame, and because each frame can include a separate set of embedded frames and parts, it is important to specify the frame whose enclosed objects are to be cloned. Otherwise, extra embedded parts or other objects not needed by the copy may be included unnecessarily. (You can specify null for the scope of a clone if you want all objects copied, regardless of what display frame they are associated with.)

In the example shown in the following figure, the user has selected some content in the root part that includes display frame 1 of embedded part A. The root part writes its intrinsic content and then clones part A, passing it a scope of frame A1. Any content that belongs only to frame A2 (such as part C) is not included in the clone.

Figure 61. Scope in Cloning



View figure.

Scope changes during the course of a clone. Continuing the example shown in the previous figure, the next figure shows how part A clones itself in the context of the scope (frame A1) specified by the root part. Part A writes the intrinsic content of its display frame A1 and then clones part B twice, first passing it a scope of frame B1 and then a scope of frame B2. Part B thus gets called to clone itself twice, with different scopes. Any content of B within frames B1 and B2 is included, but any content that belongs only to frame B3 is not.

Figure 62. Change in Scope as More Deeply Embedded Parts Are Cloned



View figure.

CloneInto Method of Your Part Editor

If your part is an embedded part that is written to the clipboard (or other data-transfer object), your part's override of its inherited CloneInto method is called by your draft's Clone method. This is the interface to CloneInto:
void CloneInto(in ODDraftKey key,
                in ODStorageUnit toSU,
                in ODFrame scope);

Your CloneInto method is passed a draft key for the clone operation and a frame that defines the scope of the cloning. The method should write your part's intrinsic content to the provided storage unit, and it should clone in turn any objects (such as embedded frames or auxiliary storage units) that it references. It needn't clone any objects or write any data that is outside of the scope.

Note:

Do not implement your CloneInto method by writing your part to storage and then cloning your storage unit. Doing so would levy performance penalties because of the extra time needed to store your data. Also, it could result in the copying of unneeded objects because the scope of the clone would be ignored.

To support efficient data transfer, your part should, if possible, write a promise (see next section) instead of writing its actual intrinsic data when CloneInto is called. It is possible to write a promise only when your part is placed into the data-transfer object as a single, standalone frame with no surrounding intrinsic content of its containing part. In any other situation, your CloneInto method might have been called to help fulfill a promise, in which case writing a promise would be inappropriate. You can determine whether you can write a promise by examining the provided storage unit. If it contains a property with the name kODPropContentFrame, your part is the sole content of the storage unit's contents property, and you can write a promise instead of actual data.

When you write a promise, be sure to identify (to yourself) the display frame or frames of your part that are within the scope of the clone operation, so that your FulfillPromise method can write the proper content when it is called.

Take these general steps in your CloneInto method:

  1. Check to see if your part has already been cloned in this operation. Because an object can be referenced more than once, its CloneInto method can be called more than once in a single cloning. In general, if a contents property already exists in the storage unit passed in the method, your part has already been cloned and there is no need to repeat the process.

    An exception to this rule occurs when scope is significant. If your part is called to clone itself with different scopes during the same operation (see, for example, the previous figure), it may have to write additional data each time its CloneInto method is called.

  2. Call your inherited CloneInto method.

  3. If it does not already exist, add a property named kODPropContents to the provided storage unit. (You do not have to call BeginClone; that method will already have been called. Also, you do not have to add properties other than the contents property; OpenDoc will add your part's name and any other needed annotations.)

  4. Check whether you can write a promise. Look for a property with the name kODPropContentFrame in the storage unit. (It is not required that any value yet exist in the property; the caller of your CloneInto method may write the value after cloning completes.)

  5. Focus on the contents property, and write a value for each part kind you support. Either write a promise or the data of your part itself, using either the storage unit's SetPromiseValue or SetValue method, respectively.

    (For data transfer, it is especially important to write a standard format in addition to your own native part kind, because the ultimate destination of the transferred data is unknown.)

  6. Clone all objects that your part references (that are within the scope of the cloning operation) as follows:

ClonePartInfo Method of Your Part Editor

Whenever your part's display frame is cloned during data transfer, the frame calls your part's ClonePartInfo method:
void ClonePartInfo(in ODDraftKey key,
                           in ODType partInfo,
                           in ODStorageUnitView,
                           in ODFrame scope);

You should respond to this method call by writing your part info into the provided storage unit view (regardless of the state of your part-info dirty flag), and cloning any objects referenced in your part info data.

Promises

   

Clipboard transfer, drag and drop, and linking can make use of promises. A promise is a specification of data to be transferred at a future time. If a data transfer involves a very large amount of data, the source part can choose to write a promise instead of actually writing the data to a storage unit. When another part retrieves the data, the source part must then fulfill the promise. The destination part does not even know that a promise is being fulfilled; it simply accepts the data as usual.

The format of a promise is completely determined by the source part. The only restriction is that the promise must be able to be written to a storage-unit value.

You are encouraged to write promises in place of actual data in most cases; it minimizes memory requirements and increases performance.

Writing a Promise

         

Your part can follow these steps to write a promise when it is the source of a data transfer. The part is the data transfer source when it responds to a mouse-down event that initiates a drag, when it copies data to the clipboard, or when it updates a link source.

  1. Gain access to the storage unit of the data-transfer object. See, for example, the initial steps under "Copying or Cutting to the Clipboard", "Initiating a Drag", and "Updating a Link at the Source". Focus the storage unit to the contents property (kODPropContents).

  2. Prepare your promise. It can have any content and format you decide; you must be able to read it later and reconstruct the exact data that is to be transferred.

  3. Write the promise into a single value of the storage unit, using the storage unit's SetPromiseValue method. Your promise must include at least this information:

  4. Write other needed information. You do not need to clone any frames or read any actual content into the data-transfer object at this stage. However, you should create a link specification, obtain an update ID, write a suggested frame shape, and so on, as described in "Writing Intrinsic Content".

Each promise you write is for a single part kind. You can write several promises representing data of several kinds, so that the destination part has a better chance of being able to incorporate the data instead of embedding it. Because promises are private data, the actual content of all your promises can be the same, regardless of the part kind being promised. When you are called to fulfill the promise, you can inspect the provided storage-unit view object to find out which part kind is needed.

Because a promise is valid only for the duration of the current instantiation of your part, the promise can contain pointers to information that you maintain.

Getting Data from a Value Containing a Promise

When the Drop method of a destination part retrieves the data from a drop, or when a destination part reads data from the clipboard (using the GetValue or GetSize methods of the dragged data's or clipboard's storage unit), the source part is called to fulfill the promise. The destination part does not even know that a promise is being fulfilled; it follows the procedures described in "Reading from a Data-Transfer Object" and uses the same code whether the value contains a promise or not.

Fulfilling a Promise

OpenDoc calls your source part's FulfillPromise method when a promise must be fulfilled, passing it a storage-unit view object that contains the data of the promise. This is its interface:
void FulfillPromise(in ODStorageUnitView promiseSUView);

In your implementation of the method, take steps similar to these:

  1. Examine the private information that you wrote into the promise earlier, to determine what data to write.

  2. Look for a property named kODPropCloneKindUsed in the storage-unit view passed to you. Your containing part may have placed the property there if your part was being cloned as a single embedded frame when your part wrote the promise. If the property exists, it contains a value of type kODCloneKind that specifies the kind of cloning transaction (such as kODCloneCopy or kODCloneCut) that you must use in fulfilling the promise.

    If the property does not exist, use information that you saved when you wrote the promise to determine the kind of cloning transaction to use.

  3. Begin a cloning operation (call to BeginClone).

  4. Retrieve the actual data that the promise represents and write it into the provided storage-unit view object, following the steps described in "Cloning Sequence". You can clone frames and other objects as usual at this time.

  5. End the cloning operation (call EndClone).

When your FulfillPromise method completes, the destination part receives the data.

When you fulfill a promise, you must be sure to supply the source content that was selected at the time the promise was written, even if that content no longer exists in your part.

If fulfilling your promise requires cloning, you must specify the scope and the appropriate kind of cloning transaction. If you have saved that information in the promise itself, extract it and pass it to your draft's BeginClone and Clone methods, respectively.

There are some times when your part may have to fulfill a promise on its own, without its FulfillPromise method having been called. For example, when your part closes, your part's ReleaseAll method (see "Closing Your Part") must fulfill all outstanding promises. To fulfill a promise in that manner, your part needs to have kept a record of the promises (and their update IDs) that it has written. Then, in ReleaseAll, it can:

You can also force fulfillment of one of your promises by focusing on the promised value and calling the GetSize method of its storage unit. That causes your FulfillPromise method to be called immediately.

Handling Cut Data

The user can remove data from your part by selecting the Cut command or by using drag and drop to move (rather than copy) data from your part into another part. In this event, you need to take extra steps to account for the fact that the data is still valid but is no longer in your part, and also to allow the action to be undone. Keep these points in mind:

Handling Pasted or Dropped Data

When data is pasted or dropped into a part, the part receiving the data can either embed the data as a separate part or incorporate the data as intrinsic content. The part may also, in some circumstances, translate the data, or it might even refuse to accept the pasted data.

This section discusses how OpenDoc and your part editor make these decisions, both with and without explicit user intervention. It also discusses when your part editor might explicitly translate data.

Default Conventions

In the absence of other instructions, OpenDoc expects your part to follow these specific conventions when pasting data from the clipboard or when accepting dropped data during a drag and drop operation.

Note:

All parts may not behave in this way depending on how they were created.

The destination part should be written to place clipboard data at the insertion point; it should place dropped data at the point where the user releases the mouse button. Note also that a pasted or dropped part takes on the view type that its containing part prefers it to have.

Handling the Paste As Dialog Box

   

The Paste As dialog box allows the user to override OpenDoc and specify whether transferred data is to be embedded, incorporated, or translated and then embedded or incorporated. It also allows the user to create a link to the source of the transferred data.

When the user chooses Paste as in the Edit menu (see "Edit Menu"), the active part should only call the ShowPasteAsDialog method on the OS/2 or Windows platforms to display the Paste As dialog box, shown in Figure 63.     On the AIX platform, the part may treat a user's "Paste As" selection as a link automatically because there is no dialog to call. Also, when the user presses Alt in a drag and drop operation, the active part should call the ODDragAndDrop::ShowPasteAsDialog method (for the OS/2 and Windows platforms). See "Dropping" for more information.

Figure 63. Paste As Dialog Box



View figure.

The user can select the following options from the dialog box:

On the OS/2 platform and the Windows platform, the ShowPasteAsDialog method returns the results of the user's choices to your part in an ODPasteAsResult structure:
struct ODPasteAsResult
{
        ODBoolean           pasteLinkSetting;
        ODBoolean           autoUpdateSetting;
        ODBoolean           mergeSetting;
        ODTypeToken         selectedView;
        ODType              selectedKind;
        ODType              translateKind;
        ODEditor            editor;
};

Depending on the contents of the returned structure, your part either embeds or incorporates the transferred data, accepts it, and either creates a link to its source or does not.


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