Managing ID attribute settings through use of cut/copy/paste callbacks

Submitted by: Liz Fraley Last Updated: 2010-11-18

=Problem=

A discussion on adepters about how to manage ID attribute settings on XML elements through use of cut/copy/paste callbacks. Brian Jensen posted this comment which prompted a great answer from Bob Beetcher:

Comment by Brian Jensen

Maybe I missed something from the discussion, but it seemed like nobody mentioned the fact that we do have access to the documents in named paste buffers using the acl function buffer_doc, which returns the doc id of the named buffer whose name you pass in. So if you catch copy events and reroute them to a named paste buffer, then catch the paste event and change the id attr in the paste buffer document before the paste occurs, you could avoid creating a separate document. Having said that, sounds to me like James' suggestion might be the easiest route.

=Solution=

Originally posted by Bob Beetcher

Just in case they're useful, I'll share some thoughts on managing ID attribute settings on XML elements through use of cut/copy/paste callbacks which we've been doing for years here at SAS. The points made below present the highlights. Of course, the details are much more involved. Most of our callback support is implemented within ACL code. A portion, that which sets new ID attribute values within content to be pasted, is implemented in java using the AOM.

cut callback
Our cut callback is used to detect when we do not need to set new ID attribute values for a subsequent paste:


 * We check for the cut being part of a drag and drop operation, in which case we don't do any special processing. We key off buffer name "_APT_DRAGDROP_PASTEBUF" to detect a drag N drop operation.
 * We maintain a global state indicator to remember when a fresh cut is placed in the paste buffer. This is used on a paste operation to avoid setting new ID attribute values when the fresh cut is the subject of a paste.

override implementation of the normal undo
We have an override implementation of the normal undo operation where we monitor for an undo operation so if, on a subsequent paste, we detect that an undo occurred while a fresh cut was in the paste buffer, we can prompt the user to determine what to do and thereby avoid the next paste possibly storing duplicate ID attribute values.

"notify" callback
Our "notify" callback is used to monitor for an activate window operation occurring which would indicate the user may have copied something else into the paste buffer through another application. So if one occurs while a fresh cut is in the paste buffer, we can verify whether the paste buffer contents have changed and if so reset the fresh cut indicator and thereby avoid the next paste possibly storing duplicate ID attribute values.

copy callback
Our copy callback is used to reset the global state indicators relating to a fresh cut being in the paste buffer.

paste callback
Our paste callback is used to set new ID attribute values within the pasted content if it is needed:


 * If the paste is coming from a a drag N drop operation, buffer name "_APT_DRAGDROP_PASTEBUF", we do not set new ID attribute values within the pasted content.
 * We do a trial pre-paste operation to determine whether the paste will succeed or fail due to an out of context error. We do this so we can ensure we only reset our fresh cut is in the paste buffer indicator for a paste that is successful. To do this trial paste we insert a pair of "_display" tags into the paste target point and then do the trial paste inside them. That allows us to test whether anything was pasted between them and to accurately remove the content of the trial paste operation before proceeding.
 * If the paste is occurring while a fresh cut is in the paste buffer, we do not set new ID attribute values within the pasted content and we reset our fresh cut indicator. Part of the processing here is to check whether an activate window occurred while the fresh cut was in the buffer, and if it did, to verify as best we can whether the current contents of the paste buffer are the same as those we saved when the cut was initially performed. If they're not, we do not set new ID attribute values. Another part of the processing here is to check whether an activate window occurred while the fresh cut was in the buffer, and if it did, to prompt the user for whether to set new or retain the old ID attribute values. We resorted to asking the user because we couldn't confidently handle all the scenarios of undo/redo operations that might occur and be sure we're doing the right thing.
 * When we need to modify the content to be pasted, we do that using a separate paste buffer for the final paste operation because making changes in the original buffer passed into the callback resulted in Epic clearing out the altered original buffer after we exited from the callback. That resulted in users complaining they could only use the paste buffer for one paste operation. We are able to modify the content to be pasted right in this separate paste buffer by getting a doc handle for it (see buffer_doc command) and then traversing the element structure within it.