Cannot undo manual invocation of ViewUtil.destroy() [message #190830] |
Tue, 03 June 2008 20:52 |
Andrew J. Montalenti Messages: 23 Registered: July 2009 |
Junior Member |
|
|
I am writing a custom GMF editor that is based upon the generated editor
from the GMF SDK. One of the issues I'm running into is what I've come to
label as 'orphaned node cleanup.'
In a non-synchronized diagram, when a model object is deleted from the
model but remains referenced from the diagram, the Node that acts as a
View on that model becomes null. (that is, view.getElement() == null) I
call this an 'orphaned Node' since its corresponding Model element is now
gone, so the Node is, essentially, meaningless. This has an affect on the
visual display of the EditPart -- for example, null connections are shown
with an 'x' over them.
(This has other problems for me outside of the aesthetic -- namely, that
some code that refreshes the connections assumes that there are no null
Nodes on the canvas, and throws a NullPointerException when orphaned Nodes
are encountered.)
So, I thought I'd be able to remedy this problem by executing code like
the following when relevant deletions are detected:
for (View view : diagram.getPersistedChildren()) {
if (view.getElement() != null) {
return;
}
// is an orphaned Node
int visualID = XXXVisualIDRegistry.getVisualID(view);
if (isTopLevelNode(view)) {
TransactionalEditingDomain editingDomain =
getEditingDomain();
// execute as GEF command
new ICommandProxy(new DeleteCommand(editingDomain,
view)).execute();
}
}
Under the hood, the GMF DeleteCommand just uses ViewUtil.destroy to kill
the orphaned Node.
This works as expected. When the code runs, the views are cleaned up.
However, the problem arises when I try to *undo* these actions. When I
undo up to the point of this command, I get the following stack trace:
!STACK 0
org.eclipse.emf.common.util.BasicEList$BasicIndexOutOfBounds Exception:
index=2, size=0
at org.eclipse.emf.common.util.BasicEList.get(BasicEList.java:5 35)
at
org.eclipse.emf.ecore.change.impl.ListChangeImpl.applyAndRev erse(ListChangeImpl.java:535)
at
org.eclipse.emf.ecore.change.impl.ChangeDescriptionImpl.preA pply(ChangeDescriptionImpl.java:474)
at
org.eclipse.emf.ecore.change.impl.ChangeDescriptionImpl.appl yAndReverse(ChangeDescriptionImpl.java:321)
at
org.eclipse.emf.transaction.util.CompositeChangeDescription. applyAndReverse(CompositeChangeDescription.java:105)
at
org.eclipse.emf.workspace.AbstractEMFOperation.doUndo(Abstra ctEMFOperation.java:525)
at
org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTr ansactionalCommand.doUndo(AbstractTransactionalCommand.java: 259)
at
org.eclipse.emf.workspace.AbstractEMFOperation.undo(Abstract EMFOperation.java:306)
at
org.eclipse.emf.workspace.CompositeEMFOperation.doUndo(Compo siteEMFOperation.java:364)
at
org.eclipse.emf.workspace.AbstractEMFOperation.undo(Abstract EMFOperation.java:306)
at
org.eclipse.gmf.runtime.common.core.command.CompositeCommand .doUndoWithResult(CompositeCommand.java:625)
at
org.eclipse.gmf.runtime.common.core.command.AbstractCommand. undo(AbstractCommand.java:215)
at
org.eclipse.gmf.runtime.common.core.command.CompositeCommand .doUndoWithResult(CompositeCommand.java:625)
at
org.eclipse.gmf.runtime.common.core.command.AbstractCommand. undo(AbstractCommand.java:215)
at
org.eclipse.core.commands.operations.DefaultOperationHistory .doUndo(DefaultOperationHistory.java:415)
at
org.eclipse.core.commands.operations.DefaultOperationHistory .undo(DefaultOperationHistory.java:1268)
at
org.eclipse.ui.operations.UndoActionHandler.runCommand(UndoA ctionHandler.java:78)
at
org.eclipse.ui.operations.OperationHistoryActionHandler$4.ru n(OperationHistoryActionHandler.java:314)
at
org.eclipse.jface.operation.ModalContext.runInCurrentThread( ModalContext.java:369)
at org.eclipse.jface.operation.ModalContext.run(ModalContext.ja va:313)
at
org.eclipse.jface.dialogs.ProgressMonitorDialog.run(Progress MonitorDialog.java:495)
at
org.eclipse.ui.internal.operations.TimeTriggeredProgressMoni torDialog.access$6(TimeTriggeredProgressMonitorDialog.java:1 )
at
org.eclipse.ui.internal.operations.TimeTriggeredProgressMoni torDialog$2.run(TimeTriggeredProgressMonitorDialog.java:203)
at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator .java:67)
at
org.eclipse.ui.internal.operations.TimeTriggeredProgressMoni torDialog.run(TimeTriggeredProgressMonitorDialog.java:216)
at
org.eclipse.ui.operations.OperationHistoryActionHandler.run( OperationHistoryActionHandler.java:329)
at
org.eclipse.gmf.runtime.common.ui.action.actions.global.Glob alUndoAction.doRun(GlobalUndoAction.java:245)
Does anyone know what's going on here?
Thanks,
Andrew
|
|
|
|
|
Re: Cannot undo manual invocation of ViewUtil.destroy() [message #191124 is a reply to message #190950] |
Wed, 04 June 2008 22:17 |
Andrew J. Montalenti Messages: 23 Registered: July 2009 |
Junior Member |
|
|
Hi Alex,
Thanks for the tip. Unfortunately, it didn't work around the issue.
Like you suggested, I wrapped my action in an AbstractEMFOperation that
had the TransactionalOption set to suppress undo. That is:
Map<String, Boolean> options = new HashMap<String, Boolean>();
options.put(Transaction.OPTION_UNPROTECTED, Boolean.TRUE);
TransactionalEditingDomain editingDomain = getEditingDomain();
AbstractEMFOperation op =
new AbstractEMFOperation(editingDomain, "Un-undo'able view delete",
options) {
@Override
protected IStatus doExecute(IProgressMonitor monitor,
IAdaptable info) throws ExecutionException {
ViewUtil.destroy(view);
return Status.OK_STATUS;
}
};
try {
op.execute(null, null);
}
catch (ExecutionException e) {
logf(CRITICAL, "Could not execute destroy view command");
}
Nonetheless, I still get the same stack trace as before.
Upon further debugging, I realized that the stack trace is occuring in
AbstractEMFOperation#doUndo, but that the concrete AbstractEMFOperation
that is failing is of type CreateCommand.
Could it be that my error is actually related to trying to undo the
*creation* of a view when that view has been manually deleted from the
semantic model? I tested and confirmed that this is the case. The
problem is that the CreateCommand expects the View to be present in the
diagram in order for its doUndo method to work properly. Since my code is
deleting that view, the CreateCommand.doUndo is failing.
Would I be right in stating that the only way for me to work around this
issue would be to provide an alternative CreateCommand that has a more
cautious doUndo implementation? One that, for example, checks to ensure
that a corresponding View exists on the canvas before attempting to
destroy as part of the Undo Create process?
Thanks,
Andrew
|
|
|
|
Powered by
FUDForum. Page generated in 0.28711 seconds