Skip to main content
1-Visitor
November 16, 2010
Question

Paste Callback ACL Question

  • November 16, 2010
  • 15 replies
  • 2633 views
Our acl code has a callback for insert_tag that detects the insertion
of specific ID elements, and assigns them a unique @ID attribute
(using the OID) upon insertion. This has worked great for years, and
due to the nature of how we were using the tags, was sufficient for
our needs.

Our new tagsets, however, lend themselves to being copy/pasted in
order to use the previous structure as the basis for new items added.
Unfortunately, the insert_tag callback does not fire on a paste.

So... I was looking into using the paste callback, but it seems that
pasted content does not trigger insert_tag, even if the given tag is
in the buffer. Furthermore, I think it might be better to use the
copy callback, since I would want the ID to remain in the case of a
cut/paste.

Does anyone know offhand if there is any easy way to interrogate the
copy/pasted tags, aside from doing some sort of search across the
actual text in the buffer?

Ultimately, all I'm trying to do is determine if the user is trying to
copy something like <tag id="id_1234"> and to automatically update the
id to something new and unique before it has been committed.

Thanks in advance for any pointers.

keith

    15 replies

    1-Visitor
    November 17, 2010
    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.





    Brian Jensen
    bjensen@bluelid.com


    1-Visitor
    November 18, 2010

    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.

    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.

    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.

    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.

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

    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.



    In Reply to 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.





    Brian Jensen
    bjensen@bluelid.com


    1-Visitor
    November 18, 2010
    Thanks for sharing, that is pretty interesting. The idea of actually prompting the user is a good one we hadn't thought of.

    In the past we tried managing behavior based on detecting copies vs. cuts, but couldn't ever get it working quite right. It ended up being easier all around to implement and explain to users a universal "if you move it, the IDs get changed" rule. Our users have to address a few more broken cross-references then they might otherwise, but that's simpler than dealing with than duplicate IDs.

    -James

    1-Visitor
    March 4, 2014
    Thanks (3+ years later) Bob!

    My initial pass at ID duplication protection did not accommodate for
    copying content with IDs *between* two Editor instances, or, if for some
    reason authors stored a table, let's say, as text or in Word or something
    else crazy-town like that. Your notes helped me do so. Like you, I could
    not detect enough conditions to write "idiot-proof" strip-or-preserve logic
    that covered all use-cases. Fortunately, however, my authors understood the
    scenario and let me strip IDs in all cases other than a those I could "do
    the right thing."





    1-Visitor
    March 4, 2014

    Paul, you are welcome. Thanks for th post It's nice to learn someone benefited from the information I shared back then.