Closed eckig closed 9 years ago
Interesting, I will look into this and get back to you asap.
Can you link the code where you create the new GConnection objects and add them to the GModel?
That is not easy, but I tried to extract it:
GConnection connection = GraphUtils.createConnection(CHILD_CONNECTION, pOutputConnector, childInput,
new Point2D(getNode().getX() + getNode().getWidth(), getNode().getY()),
new Point2D(node.getX(), node.getY()));
EMFUtils.addCommand(model, pNewNode)
.append(EMFUtils.addCommand((EProcessModel) getStep().eContainer(), pNewStep))
.append(EMFUtils.addCommand(model, pConnection))
.append(EMFUtils.addCommand(model, pConnection.getSource(), pConnection))
.append(EMFUtils.addCommand(model, pConnection.getTarget(), pConnection));
command.execute();
pOutputConnector is the given output GConnector where the new node is to be attached to. childInput is the new GConnector of the new GNode. EMFUtils is my utiltiy class helping with the EMF commands (shorter to write, builder pattern, ..).
And the mentioned method:
public static GConnection createConnection(String pConnectionType, GConnector pSource, GConnector pTarget, Point2D pSourcePoint,
Point2D pTargetPoint)
{
Point2D middle = pSourcePoint.midpoint(pTargetPoint);
GConnection connection = GraphFactory.eINSTANCE.createGConnection();
connection.setType(pConnectionType);
connection.setSource(pSource);
connection.setTarget(pTarget);
connection.getJoints().add(createJoint(middle.getX(), pSourcePoint.getY()));
connection.getJoints().add(createJoint(middle.getX(), pTargetPoint.getY()));
return connection;
}
Looking at your code I assume that the eContainer of the target of the connection should be 'pNewNode'. Can you make sure you are calling
pNewNode.getConnectors().add(childInput)
before the command is executed?
I thought EMF does that?
Edit: I already do that. Edit#2: It is not the programmatically added connection that causes the NPE. The connection I created via Drag and Drop afterwards does.
We use EMF 'EOpposites' in the simple cases, for example if you call
pNewNode.getConnectors().add(childInput)
then 'childInput' will automatically have it's parent set to 'pNewNode', as if you had also called
childInput.setParent(pNewNode)
You just need to call either one, and it needs to be called before you execute your command.
Unfortunately for slightly more complicated relationships we could not use this mechanism so you have to specify everything, e.g.:
newConnection.setSource(newSource);
newConnection.setTarget(newTarget);
newSource.getConnections().add(newConnection);
newTarget.getConnections().add(newConnection);
I also just noticed, make sure you are calling
if (command.canExecute()) {
editingDomain.getCommandStack().execute(command);
}
rather than
command.execute();
directly. The former will trigger the command stack listener that updates the view.
Ok I finally found the problem: The first GConnector was added via EMF and thus working fine with undo and redo. The second connector was not added via EMF commands and that caused the problems.
Ok great. I added some additional logging whenever the model state changes that will hopefully make it easier to detect errors like this in the future.
Ok. Thanks anyway and always good to have additional logging.
I debugged this a lot but I can not find the source of this issue.. In your demo application everything works fine, in my application not.
Reproduction:
Redoing the last change (last connection added) produces the following:
I can see why this is happening: The eContainer of the target of the connection is null. But I do not know why. When the connection is created everything is fine, if I undo and redo the connection the eContainer is gone. For testing purposes I unhooked my domain model but that does not change anything..