Different behavior between undo and redo [message #1734461] |
Wed, 08 June 2016 14:18 |
Laurent Le Moux Messages: 44 Registered: June 2015 |
Member |
|
|
Hi all,
I made the following test. I import the Graphiti tutorial example and change TutorialRenameEClassFeature to implement ICustomUndoRedoFeature.
I simply return false in the canRedo method.
From there, I launch the application, create a diagram, add a new class and change its name. I can undo the renaming. TutorialRenameEClassFeature.canUndo is called and returns true.
But... I can also perform a redo ! And TutorialRenameEClassFeature.canRedo is not called until the redo actually takes place.
Before the undo is proposed in the context menu to the user, canUndo is called to check whether the undo can take place. And, during undo execution, canUndo is called once again to check whether the feature pre/postUndo methods have to be executed (see GFWorkspaceCommandStackImpl.undo()).
In a redo situation, canRedo is not called to check whether the redo should actually take place. Only during redo execution will it be called to check whether the feature pre/postRedo methods have to be executed.
In other words, there is no way to prevent the EMF redo to take place.
GFWorkspaceCommandStackImpl.canUndo execution leads to TutorialRenameEClassFeature.canUndo call.
Whereas GFWorkspaceCommandStackImpl.canRedo does not...
This is due to a slight difference in GFPreparableCommand2 between canUndo and canRedo.
GFPreparableCommand2.canUndo overrides the default behavior as follow:
@Override
public boolean canUndo() {
return getCommand().canUndo() && super.canUndo();
}
getCommand().canUndo() causes the feature canUndo to be called while super.canUndo() checks EMF RecordingCommand.canApplyChange().
There is no override for the parent class RecordingCommand.canRedo which only calls canApplyChange()...
Adding getCommand().canRedo() is not possible as getCommand() returns a Graphiti EmfOnGefCommand class that implements EMF Command interface and not the ConditionalRedoCommand one.
From what I've seen (to be confirmed), changing this in Graphiti internals is not straightforward and has impacts in several places.
Therefore, to have the feature canRedo being called to check if redo can take place, I suggest to override canRedo in GFWorkspaceCommandStackImpl as follow :
/**
* Make sure canRedo is called for features implementing ICustomUndoRedoFeature.
*/
@Override
public boolean canRedo() {
Command redoCmd = getRedoCommand();
if (redoCmd != null && redoCmd instanceof GFPreparableCommand2) {
Command wrappedCmd = ((GFPreparableCommand2) redoCmd).getCommand();
if (wrappedCmd != null && wrappedCmd instanceof EmfOnGefCommand) {
org.eclipse.gef.commands.Command innerCmd = ((EmfOnGefCommand) wrappedCmd).getGefCommand();
if (innerCmd != null && innerCmd instanceof GefCommandWrapper) {
ICommand cmd = ((GefCommandWrapper) innerCmd).getCommand();
if (cmd != null && cmd instanceof GenericFeatureCommandWithContext) {
IFeature feature = ((GenericFeatureCommandWithContext) cmd).getFeature();
IContext context = ((GenericFeatureCommandWithContext) cmd).getContext();
if (feature instanceof ICustomUndoRedoFeature)
return ((ICustomUndoRedoFeature) feature).canRedo(context) && super.canRedo();
}
}
}
}
return super.canRedo();
}
Kind regards,
Laurent
[Updated on: Wed, 08 June 2016 14:22] Report message to a moderator
|
|
|
|
|
Powered by
FUDForum. Page generated in 0.03466 seconds