Page 1 of 1

Copy/Paste event

Posted: Fri Jan 11, 2019 8:17 pm
by Isabelle
Hello,

We use oxygen-18.1.0.0.jar, and we need to add specific work on copy/paste event.
We have this king of element :

Code: Select all


<Paragraph>
<BlocText>
<Phr code="0124254201063" locale="fr_FR">
<text>Some Text</text>
</Phr>
</BlocText>
</Paragraph>
When we want to copy the <text/> element, we need to take the <Phr/> parent too in order to keep the attributes code and locale.

I tried to update the method
ro.sync.ecss.extensions.api.content.ClipboardFragmentProcessor#process(ro.sync.ecss.extensions.api.content.ClipboardFragmentInformation)


But at this moment we only have the <text/> element and not his parent anymore.

Is it possible to update the fragment in the clipboard before we loose the parent information of the copied element ?
On the copy event for exemple ?

Regards,
Isabelle

Re: Copy/Paste event

Posted: Mon Jan 14, 2019 10:00 am
by Radu
Hi Isabelle,

The "ClipboardFragmentProcessor" is called on the clipboard content, so indeed as you found out it's too late to do something about this after the object has been cloned and copied to the clipboard.
Maybe if you add a listener before the "Copy" action is being executed you could try to adjust the offsets of the selection, something like:

Code: Select all

    WSAuthorEditorPage authorPage = ......;
AuthorActionsProvider actionsProvider = authorPage.getActionsProvider();
Object copyAction = authorPage.getActionsProvider().getAuthorCommonActions().get("Edit/Edit_Copy");
authorPage.getActionsProvider().addActionPerformedListener(copyAction, new ActionPerformedListener() {
/**
* @see ro.sync.exml.workspace.api.editor.page.author.actions.ActionPerformedListener#beforeActionPerformed(java.lang.Object)
*/
@Override
public boolean beforeActionPerformed(Object actionEvent) {
//Maybe here you can look at the current selection offsets and adjust them before the action is done
// authorPage.getSelectionStart()
// authorPage.getSelectionEnd()
// authorPage.getAuthorAccess().getDocumentController().getNodeAtOffset(offset)
return true;
}
});
so that the Copy action will copy the entire <Phr> element to the clipboard.

Regards,
Radu

Re: Copy/Paste event

Posted: Mon Jan 14, 2019 1:54 pm
by Isabelle
Hello Radu,

Thank you for your answer.
I have tried to implement your solution but I face two issues :
- 1) Your solution is available for Author mode, but what happen in Text mode ?
The code

Code: Select all

authorActionProvider.addActionPerformedListener(copyAction, new ActionPerformedListener()

Re: Copy/Paste event

Posted: Mon Jan 14, 2019 2:02 pm
by Isabelle
I am sorry, I have posted too early.

1) In Text mode you don't have the code

Code: Select all

authorActionProvider.addActionPerformedListener(copyAction, new ActionPerformedListener()
available.
So, how can I handle copy event in this mode ?

2) In the

Code: Select all

beforeActionPerformed
method, I can retrieve the node currently selected but I don't find out how to change the selection.
I have the methods

Code: Select all

authorPage.getSelectionStart()
and

Code: Select all

authorPage.getSelectionEnd()
, but I don't have the setter for Start and End selection or a setter for selection node. So how can I update the current selection ?

Thanks,
Isabelle

Re: Copy/Paste event

Posted: Tue Jan 15, 2019 1:02 pm
by Radu
Hi Isabelle,

There is also a more global API to get access to some actions:

Code: Select all

    ActionsProvider actionsProvider = ((StandalonePluginWorkspace)PluginWorkspaceProvider.getPluginWorkspace()).getActionsProvider();
Map<String, Object> globalActions = actionsProvider.getGlobalActions();
Object copy = globalActions.get("Edit/Edit_Copy");
actionsProvider.addActionPerformedListener(copy, new ActionPerformedListener() {
/**
* @see ro.sync.exml.workspace.api.editor.page.author.actions.ActionPerformedListener#beforeActionPerformed(java.lang.Object)
*/
@Override
public boolean beforeActionPerformed(Object actionEvent) {
System.err.println("BEFORE PERFORMED");
return true;
}
});
and this works also for the text page but from what I tested only when the "Copy" action is invoked from the main menu.
When the "Ctrl-C" shortcut is used you could try to intercept that by gaining access to the JTextArea using WSTextEditorPage.getTextComponent() and then looking in its input map, try to replace the mapping for "Ctrl-C" with your own action which wraps the current Copy action.
When the "Copy" action is invoked from the contextual menu you could again use the API ro.sync.exml.workspace.api.editor.page.text.WSTextEditorPage.addPopUpMenuCustomizer(TextPopupMenuCustomizer) to wrap the current "Copy" action in your own.

About (2), in all editing pages including the Author visual editing mode you have the API ro.sync.exml.workspace.api.editor.page.WSTextBasedEditorPage.select(int, int).

Possibly we could try to add new API for this if we come to an agreement about how this API could look like (API to allow you to maybe set some custom properties in the clipboard along with the content) but I'm not sure in what Oxygen version we can do that. Oxygen 21 will be released in about a month and we are not adding new API to it.

Regards,
Radu

Re: Copy/Paste event

Posted: Tue Jan 15, 2019 7:35 pm
by Isabelle
Hi Radu,

The API ro.sync.exml.workspace.api.editor.page.WSTextBasedEditorPage.select(int, int). works fine, Thanks.

Regarding the Text mode, we will improve it in a futur release.

But I still have issue with the contextual menu.
The solution in your first post works fine for the "Copy" action of the main menu and the "Ctrl-C".
But not for the contextual menu.
I have tried the solution of a PopUpMenuCustomizer but in that specific case I can not add an ActionPerformedListener.
This kind of listener is not available for JMenuItem element and I only can improve ActionListener.
But it is launched after the action is performed.

Is it possible to change/modify the ClipboardFragmentInformation directly ?
I know, it is possible to create an AuthorDocumentFragment from the document via the API authorPage.getAuthorAccess().getDocumentController().createDocumentFragment(startCaret, endCaret);
Is it possible to use it to replace the fragment in the clipboard ?
Or maybe update nodes in ClipboardFragmentInformation.getFragment().getContentNodes() ?

Thanks for your help,
Regards,
Isabelle

Re: Copy/Paste event

Posted: Wed Jan 16, 2019 9:52 am
by Radu
Hi Isabelle,

So:
I have tried the solution of a PopUpMenuCustomizer but in that specific case I can not add an ActionPerformedListener.
This kind of listener is not available for JMenuItem element and I only can improve ActionListener.
But it is launched after the action is performed.
Once you get access to the "Copy" JMenuItem you are interested in, you can get its internal swing "AbstractAction", then you can create your own Swing action with the same name and icon which wraps the "AbstractAction" you found in the JMenuItem. In this way your action will be called first, you change the selection and invoke the original action.
Or as an alternative this might also work (but you would need to test it):

Code: Select all


((StandalonePluginWorkspace)PluginWorkspaceProvider.getPluginWorkspace()).getActionsProvider().addActionPerformedListener(((JMenuItem)item).getAction, listener);
but you would need to take care not to add the same listener twice to the same action because the popup menu customizer is called every time the end user right clicks.
Is it possible to change/modify the ClipboardFragmentInformation directly ?
I know, it is possible to create an AuthorDocumentFragment from the document via the API authorPage.getAuthorAccess().getDocumentController().createDocumentFragment(startCaret, endCaret);
Is it possible to use it to replace the fragment in the clipboard ?
Or maybe update nodes in ClipboardFragmentInformation.getFragment().getContentNodes() ?
That's why I mentioned that we should maybe add new API. Somehow if we had this new API, when the "Copy" operation is invoked, Oxygen could call back to your code and tell you what fragments it will copy in the clipboard, allow you to modify the fragments and also maybe add some custom objects to the clipboard (maybe a set of properties). Then on the "Paste" somehow your code would be invoked again and you would receive those custom properties back, properties which might give you indications about how to change the document fragment. I'll add an issue on our side to look into this.

Regards,
Radu

Re: Copy/Paste event

Posted: Wed Jan 16, 2019 6:34 pm
by Isabelle
Hi Radu,

I have decided to add a PopupMenuListener on the pop-up menu.
In the method popupMenuWillBecomeVisible, I check the selection and if it is a Text element which is selected, I change the selection by his parent element with

Code: Select all

authorPage.select(node.getParent().getStartOffset(), node.getParent().getEndOffset());
But It only corrects partially my problem.
I have two behavior :
- 1) If I select text in the node Text, it works fine
- 2) If my TagsDisplayMode is Full_tags and I click on the Text tag directly, even if my code is executed, the copy event only take the Text node and not his parent like I have changed before.

Any idea of what happen ?
Why do we have this two different behavior ?

Regards,
Isabelle

Re: Copy/Paste event

Posted: Thu Jan 17, 2019 12:17 pm
by Radu
Hi Isabelle,

So about the remaining problem:
- 2) If my TagsDisplayMode is Full_tags and I click on the Text tag directly, even if my code is executed, the copy event only take the Text node and not his parent like I have changed before.
I looked in our code and indeed in the case when a node is fully selected our code creates special contextual Copy and Cut actions which have references to the already selected node. So even if you change the selection, the action is done on the node which was selected when the popup is shown. I will probably add an issue on our side to change this.

A workaround is that in your wrapper "Copy" action that you add to the popup menu instead of delegating to the "Copy" action added by Oxygen to the popup you delegate to this action instead:

Code: Select all


Object originalCopyAction = authorPage.getActionsProvider().getAuthorCommonActions().get("Edit/Edit_Copy");
authorPage.getActionsProvider().invokeAction(originalCopyAction);
Regards,
Radu

Re: Copy/Paste event

Posted: Thu Jan 17, 2019 1:49 pm
by Isabelle
Hi Radu,

Thanks a lot, your workaround works fine.
Now I have the same behavior in any case of copy.

Thanks again,
Regards,
Isabelle

Re: Copy/Paste event

Posted: Wed Mar 13, 2019 8:38 pm
by Isabelle
Hello,

I need to implement the same behavior on the "drag and drop" action.

Currently, we have the same issue than with copy action.
When user have TagsDisplayMode in Full_tags mode and click on the element tag directly.
Then they drag and drop it somewhere else in the document and the attribute have wrong values.

What is the name of this action ?
I don't find it in

Code: Select all

authorActionProvider.getAuthorCommonActions()
, like "Edit/Edit_Copy".

Thanks,
Regards,
Isabelle

Re: Copy/Paste event

Posted: Thu Mar 14, 2019 3:25 pm
by Radu
Hi Isabelle,

Drag and drop is not a simple action, it's a behavior which involves a drag gesture listener (responsible of producing the transferred object) the and a drop target listener which intercepts the drop and inserts the content.
For the first part, maybe if you add a mouse listener ro.sync.exml.workspace.api.editor.page.author.WSAuthorEditorPageBase.addAuthorMouseListener(AuthorMouseListener) you could intercept the mouse dragged event ro.sync.ecss.extensions.api.AuthorMouseListener.mouseDragged(AuthorMouseEvent) and maybe change the current selection to contain the entire element, but this needs to be tested, as it might not work.
Or you could add a caret listener ro.sync.exml.workspace.api.editor.page.author.WSAuthorEditorPageBase.addAuthorCaretListener(AuthorCaretListener) and every time an element is selected you could programatically select its parent element.

Regards,
Radu

Re: Copy/Paste event

Posted: Thu Mar 14, 2019 5:08 pm
by Isabelle
Hi Radu,

Thanks a lot for your answer.

I add a mouse listener

Code: Select all

ro.sync.exml.workspace.api.editor.page.author.WSAuthorEditorPageBase.addAuthorMouseListener(AuthorMouseListener)
and I intercept the mouse dragged event

Code: Select all

ro.sync.ecss.extensions.api.AuthorMouseListener.mouseDragged(AuthorMouseEvent)
, then I update the current selection to contain the entire element.

It works perfectly for me.

Regards,
Isabelle

Re: Copy/Paste event

Posted: Fri Mar 15, 2019 8:28 am
by Radu
Hi Isabelle,

Great, I'm glad this solved your problem.

Regards,
Radu