Home » Modeling » EMF » EMF Model Editor - Customized Copy/Paste Action
EMF Model Editor - Customized Copy/Paste Action [message #762654] |
Thu, 08 December 2011 13:01 |
Ralph P Messages: 30 Registered: September 2010 Location: Frankfurt, Germany |
Member |
|
|
Hello,
I'm trying to customize the Copy/Paste mechanism in my generated model editor.
My customization contains a dialog where the user must enter a new ID for the copied object.
I started by implementing a new EditingDomainViewerDropAdapter, which worked fine until I realized that my logic works only for drag & drop does not change the behavior of copy & paste (of course!).
Browsing through this forums, I read that overriding MyItemProvider#createInitializeCopyCommand(...) is the right approach. But when I found out, that this method is called every time I use "Copy" at runtime (not Paste), I extended the CopyCommand. In MyCopyCommand I've overridden the execute() method, because I thought "on "Copy" the CopyCommand is created, and on "Paste" it should be executed". But that's not true. The CopyCommand is created and executed when I only use "Copy". Obviously there must a difference when using "Copy" or "Paste" - and this is what I'm looking for!
My custom CopyCommand works fine, but I get the "Change ID"-Dialog two times (on Copy and on Paste).
MyItemProvider:
@Override
protected Command createCopyCommand(EditingDomain pDomain, EObject pOwner,
Helper pHelper) {
return new MyCopyCommand(pDomain, pOwner, pHelper);
}
MyCopyCommand:
@Override
public void execute() {
super.execute();
// What I need is something like:
// if(!_paste)
// return;
getNewObjectIDs(getResult());
renameCopiedResources(getResult());
}
Thanks in advance!
Ralph
|
|
|
Re: EMF Model Editor - Customized Copy/Paste Action [message #762666 is a reply to message #762654] |
Thu, 08 December 2011 13:23 |
Ed Merks Messages: 33142 Registered: July 2009 |
Senior Member |
|
|
Ralph,
Comments below.
On 08/12/2011 5:01 AM, r.pakosch wrote:
> Hello,
>
> I'm trying to customize the Copy/Paste mechanism in my generated model
> editor.
>
> My customization contains a dialog where the user must enter a new ID
> for the copied object.
User interactions as part of a command are often rather tricky. After
all, the user can generally cancel an interaction...
>
> I started by implementing a new EditingDomainViewerDropAdapter, which
> worked fine until I realized that my logic works only for drag & drop
> does not change the behavior of copy & paste (of course!).
Yes, there are lots of fine grained things going on under the covers and
you generally need to focus on those...
> Browsing through this forums, I read that overriding
> MyItemProvider#createInitializeCopyCommand(...) is the right approach.
> But when I found out, that this method is called every time I use
> "Copy" at runtime (not Paste), I extended the CopyCommand.
Yes, commands are prepared and tested for excutability to populate menus.
> In MyCopyCommand I've overridden the execute() method, because I
> thought "on "Copy" the CopyCommand is created, and on "Paste" it
> should be executed". But that's not true. The CopyCommand is created
> and executed when I only use "Copy". Obviously there must a difference
> when using "Copy" or "Paste" - and this is what I'm looking for!
One can do a copy, which copies to the clipboard, and an hour later do
a paste, or perhaps never do a paste.
>
> My custom CopyCommand works fine, but I get the "Change ID"-Dialog two
> times (on Copy and on Paste).
If you think about it, if you copy something to the clipboard, you might
change the original, so you need a copy in the clipboard. Once you
paste from the clipboard, you might paste it a second time, so you
really need to paste a copy of what's in the clipboard, or at least put
a copy back in the clipboard...
>
> MyItemProvider:
> @Override
> protected Command createCopyCommand(EditingDomain pDomain, EObject
> pOwner,
> Helper pHelper) {
> return new MyCopyCommand(pDomain, pOwner, pHelper);
> }
>
> MyCopyCommand:
> @Override
> public void execute() {
> super.execute();
> // What I need is something like:
> // if(!_paste)
> // return;
> getNewObjectIDs(getResult());
> renameCopiedResources(getResult());
> }
Is there any way for the user to change the ID of an existing object?
If so, how do you deal with duplicates should they cause those?
Perhaps a better approach is to specialize copy not to copy the ID, and
to do something more general, like listen to the command stack and check
the command result to scan for objects without an ID and then present
the user with the option to set them.
If you do want to specialize paste itself, you should look at
specializing AdapterFactoryEditingDomain.createCommand and handle
PasteFromClipboardCommand in some special way.
>
> Thanks in advance!
> Ralph
Ed Merks
Professional Support: https://www.macromodeling.com/
|
|
| | |
Re: EMF Model Editor - Customized Copy/Paste Action [message #763215 is a reply to message #762708] |
Fri, 09 December 2011 11:11 |
Ralph P Messages: 30 Registered: September 2010 Location: Frankfurt, Germany |
Member |
|
|
Hello Ed,
I've successfully implemented a specialized PasteFromClipboardCommand (thanks again!).
There's one thing left that's not working how I want it:
CustomPasteFromClipboardCommand:
@Override
public void doExecute() {
super.doExecute();
try {
getNewObjectIDs(getResult());
} catch (OperationCanceledException e) {
// User canceled the rename dialog
// TODO undo does not work properly
_editingDomain.getCommandStack().undo();
return;
}
renameCopiedResources(getResult());
}
The "undo" leads to strange results (in some cases to "phantom objects" which don't physically exist but are visible in the editor). What am I doing wrong here?
Thank you!
Ralph
For others: How I implemented a custom paste action:
Specialized AdapterFactoryEditingDomain:
public class CustomAdapterFactoryEditingDomain extends
AdapterFactoryEditingDomain {
public CustomAdapterFactoryEditingDomain(AdapterFactory pAdapterFactory,
CommandStack pCommandStack,
Map<Resource, Boolean> pResourceToReadOnlyMap) {
super(pAdapterFactory, pCommandStack, pResourceToReadOnlyMap);
}
@Override
public Command createCommand(Class<? extends Command> pCommandClass,
CommandParameter pCommandParameter) {
if (pCommandClass.equals(PasteFromClipboardCommand.class)) {
return new CustomPasteFromClipboardCommand(this,
pCommandParameter.getOwner(),
pCommandParameter.getFeature(),
pCommandParameter.getIndex(), getOptimizeCopy());
}
return super.createCommand(pCommandClass, pCommandParameter);
}
}
Instantiated by the editor:
protected void initializeEditingDomain() {
<...>
//
// Create the editing domain with a special command stack.
//
editingDomain = new CustomAdapterFactoryEditingDomain(adapterFactory,
commandStack, new HashMap<Resource, Boolean>());
}
doExecute() method over
|
|
|
Re: EMF Model Editor - Customized Copy/Paste Action [message #763222 is a reply to message #763215] |
Fri, 09 December 2011 11:21 |
Ed Merks Messages: 33142 Registered: July 2009 |
Senior Member |
|
|
Comments below.
On 09/12/2011 3:11 AM, r.pakosch wrote:
> Hello Ed,
>
> I've successfully implemented a specialized PasteFromClipboardCommand
> (thanks again!).
>
> There's one thing left that's not working how I want it:
>
> CustomPasteFromClipboardCommand:
> @Override
> public void doExecute() {
> super.doExecute();
> try {
> getNewObjectIDs(getResult());
> } catch (OperationCanceledException e) {
> // User canceled the rename dialog
> // TODO undo does not work properly
> _editingDomain.getCommandStack().undo();
Have a look to see what command stack execute is doing when you call
this and you'll see that you'll be making a complete mess of the command
stack. You'll also noticed you can throw AbortExecutionException.
> return;
> }
> renameCopiedResources(getResult());
> }
>
> The "undo" leads to strange results (in some cases to "phantom
> objects" which don't physically exist but are visible in the editor).
> What am I doing wrong here?
That's not surprising...
>
> Thank you!
> Ralph
>
>
> For others: How I implemented a custom paste action:
> Specialized AdapterFactoryEditingDomain:
> public class CustomAdapterFactoryEditingDomain extends
> AdapterFactoryEditingDomain {
>
> public CustomAdapterFactoryEditingDomain(AdapterFactory
> pAdapterFactory,
> CommandStack pCommandStack,
> Map<Resource, Boolean> pResourceToReadOnlyMap) {
> super(pAdapterFactory, pCommandStack, pResourceToReadOnlyMap);
> }
>
> @Override
> public Command createCommand(Class<? extends Command> pCommandClass,
> CommandParameter pCommandParameter) {
> if (pCommandClass.equals(PasteFromClipboardCommand.class)) {
> return new CustomPasteFromClipboardCommand(this,
> pCommandParameter.getOwner(),
> pCommandParameter.getFeature(),
> pCommandParameter.getIndex(), getOptimizeCopy());
> }
> return super.createCommand(pCommandClass, pCommandParameter);
> }
> }
>
>
> Instantiated by the editor:
> protected void initializeEditingDomain() {
> <...>
> //
> // Create the editing domain with a special command stack.
> //
> editingDomain = new
> CustomAdapterFactoryEditingDomain(adapterFactory,
> commandStack, new HashMap<Resource, Boolean>());
> }
>
>
> doExecute() method over
Ed Merks
Professional Support: https://www.macromodeling.com/
|
|
| |
Re: EMF Model Editor - Customized Copy/Paste Action [message #763340 is a reply to message #763301] |
Fri, 09 December 2011 15:38 |
Ed Merks Messages: 33142 Registered: July 2009 |
Senior Member |
|
|
COmments below.
On 09/12/2011 6:36 AM, r.pakosch wrote:
> Hello Ed,
>
> sorry for asking again!
>
> 1) Why do I mess up the command stack by undoing the paste command?
You can answer this yourself by setting a breakpoint in your excute
method, looking up the stack, and see what the command stack is
doing. (You'll see that you're undo the previously execute command,
not this one, and you'll still record this one.
> Is there a way to do this correctly (obviously yes, because it's
> possible in the editor)?
> doUndo() works as long as the copied object is visible in the editor.
> Otherwise: "phantom object"
> @Override
> public void doExecute() {
> super.doExecute();
> try {
> getNewObjectIDs(getResult());
> } catch (OperationCanceledException e) {
> doUndo();
You've changed what you showed before, but you still need to be sure
that this command is not recorded on the command stack. I already
suggested how to do that...
> return;
> }
> renameCopiedResources(getResult());
> }
>
> 2) Before the execution of the PasteFromClipboardCommand I can get the
> corresponding EObjects by _editingDomain.getClipboard(). Unfortunately
> these don't contain their containers (eObj.eContainer() -> null). Is
> there a method to always find the container of an EObject?
Yes, eContainer(), which is null when there isn't a container and then
nothing will find it because there isn't one. Of course the objects in
the clipboard is already a copy that's not contained anywhere and not
referenced by anything (but the clipboard).
> If yes, I don't need to undo the copy command (because I can get the
> new IDs before the execution).
You can look closely at what PasteFromClipboardCommand. prepare does.
It would certainly be possible to create the copy but avoid doing the
add until you're sure you want to go ahead with execution.
>
> Best regards,
> Ralph
>
Ed Merks
Professional Support: https://www.macromodeling.com/
|
|
| |
Goto Forum:
Current Time: Fri Apr 26 15:17:52 GMT 2024
Powered by FUDForum. Page generated in 0.04052 seconds
|