Home » Archived » GEF3D » Renamed: How to add InterModelConnections properly(Working with GEF3D, I am facing serious lacks of knowledge concerning the creation of InterModelConnections)
Renamed: How to add InterModelConnections properly [message #789037] |
Thu, 02 February 2012 14:25 |
Lukas Olbrich Messages: 17 Registered: October 2010 |
Junior Member |
|
|
Dear Jens, dear Karsten, hi everyone,
I am currently working on a visualisation of inter-model-connections. The background is copying complex objects where we store a reference from the copies to the copied objects. I need to visualise these references for debugging purposes .
Well, I was successfull in visualising the different objects by 3difying the available editors we implemented. Now, I am trying to display the intermodel-relations, i.e. the backreferences from copy to copy template.
I used the publications from the eclipse magazines and then found your example of displaying graphs: org.eclipse.gef3d.examples.graph . There I found the usage of InterModelContainer, this is in my implementation a TIReferenceModel, which is capable of computing the references from copy to copy template. The editPart for this is TIReferenceModelEditPart, which extends AbstractConnectionEditPart just like InterModelContainerPart does in the example. The Figure of this part is a TIReferenceModelFigure which extends InterModelDiagramFigure, just like in the example.
My TIReferenceModelEditPart returns all computed backreferences as modelChildren.
The desired behaviour for the creation of a MultiEditor is the following:
I open the editor on an object that has been copied (several times), the copies i call instances. These copies might have also been copied, thus there exist instances referencing the previous instances. This leads to a tree structure. The object I open the editor on is the root.
Now, for each node of the instantiation tree a 3dified editor will be added. This is executed successfully. Then, for each instance I compute a TIReferenceModel and add an Editor for this model.
This action results in a ClassCastException:
TIReferenceModelFigure cannot be cast to org.eclipse.draw2d.Connection.
It occures when I initialise the nested editor for for my TIReferenceModel (see below). My brute force attempt was to just let the figure implement Connection, which leads to an IndexOutOfBounds on the MultiModelContainerFigure (or sth. like that, sry, I cannot recall the name but it seemed to be the Figure of the MultiEditor's rootEditPart).
Well, I was wondering what I might be missing. I do get that the cast is not correct, but this results from the extension of AbstractConnectionEditPart. Why does this not lead to an error in your implementation, or rather what do I do different than you in the example.
What I see is different is that you only create one InterModelContainer whereas I create numerous and thus numerous nested editors for these containers are created.
Thanks a lot for any help provided!
Best regards,
Lukas
at org.eclipse.gef.editparts.AbstractConnectionEditPart.getConnectionFigure(AbstractConnectionEditPart.java:148)
at org.eclipse.gef.editparts.AbstractConnectionEditPart.refreshSourceAnchor(AbstractConnectionEditPart.java:234)
at org.eclipse.gef.editparts.AbstractConnectionEditPart.refresh(AbstractConnectionEditPart.java:224)
at org.eclipse.gef.editparts.AbstractEditPart.addNotify(AbstractEditPart.java:252)
at org.eclipse.gef.editparts.AbstractGraphicalEditPart.addNotify(AbstractGraphicalEditPart.java:223)
at org.eclipse.gef.editparts.AbstractConnectionEditPart.addNotify(AbstractConnectionEditPart.java:100)
at org.eclipse.gef.editparts.AbstractConnectionEditPart.setParent(AbstractConnectionEditPart.java:268)
at org.eclipse.gef.editparts.AbstractEditPart.addChild(AbstractEditPart.java:209)
at org.eclipse.gef3d.ext.multieditor.MultiEditorModelContainerEditPart.propertyChange(MultiEditorModelContainerEditPart.java:149)
at java.beans.PropertyChangeSupport.firePropertyChange(PropertyChangeSupport.java:339)
at java.beans.PropertyChangeSupport.firePropertyChange(PropertyChangeSupport.java:276)
at org.eclipse.gef3d.ext.multieditor.MultiEditorModelContainer.add(MultiEditorModelContainer.java:86)
at de.bitub.proitbau.core.ui.ti.process.gef3d.TIReferencesEditor3D.initializeAsNested(TIReferencesEditor3D.java:58)
[Updated on: Fri, 03 February 2012 12:07] Report message to a moderator
|
|
| |
Re: Renamed: How to add InterModelConnections properly [message #789798 is a reply to message #789037] |
Fri, 03 February 2012 12:22 |
|
Lukas,
while answering your question, I found a bug in the Graph example. Actually, it is not a real bug, but I figure it is the reason for some confusion: the InterModelContainerPart did extend AbstractConnectionEditPart. This is wrong. The container is not a connection itself. I have fixed this: InterModelContainerPart extends AbstractGraphicalEditPart now. While this does no harm in the graph example, it might will wrongly leads to the assumption that the container is a connection itself. (Note: GEF3D is now stored in a Git repository, I have updated the Wiki page accordingly). You do not have to update for that reason, as it does not change the graph example in any way.
I'm not quite sure if I've understood your configuration. You have some models already being displayed in a multi editor. Now, you have a third model, the inter model. Usually, a model consists of some kind of root container and then some elements. You only mention the root model element TIReferenceModel. I try to make a list and compare your things with the graph example:
Lukas Graph
Root:
M TIReferenceModel IntermodelContainer
C TIReferenceModelEditPart IntermodelContainerPart
extends AbstractConnectionEditPart extends AbstractGraphicalEditPart
V TIReferenceModelFigure IntermodelContainerFigure
InterModelDiagramFigure extends InterModelDiagramFigure
Inter model/diagram connection (IMC)
M Edge
C IntermodelEdgePart
extends AbstractConnectionEditPart3D
V EdgeFigure3D
extends PolylineConnection3D
What I'm missing in your description is the inter model/diagram connection (IMC) MVC triple.
While I'm not sure at the moment, but I figure you have to provide a root MVC for the IMCs, and then an MVC for each IMC. As far as I understand your project, you will have to reorganize it a little bit and introduce some kind of container for your TIReferences. Something like that:
Lukas Graph
Root:
M TIReferenceModelContainer IntermodelContainer
C TIReferenceModelContainerEditPart IntermodelContainerPart
extends AbstractGraphicalEditPart extends AbstractGraphicalEditPart
V TIReferenceModelContainerFigure IntermodelContainerFigure
InterModelDiagramFigure extends InterModelDiagramFigure
Inter model/diagram connection (IMC)
M TIReferenceModel Edge
C TIReferenceModelEditPart IntermodelEdgePart
extends AbstractConnectionEditPart3D extends AbstractConnectionEditPart3D
V TIReferenceModelFigure EdgeFigure3D
extends PolylineConnection3D extends PolylineConnection3D
That is, you calculate the TIReferenceModel, add it to the TIReferenceModelContainer, and then refresh the container. However, this will work only if the models your are connecting are aware of the TIReferenceModel. If this is not the case, you will have to use the UndirectConnectionEditPart3D or introduce ConnectedElementAdapter. I figure you can use the former as you can modify your edit part of the 3Dfied elements in order to support connection anchors for the inter model connections. If you cannot modify these edit parts, you will have to use the later. See the Eclipse Magazin article (part 2) and the package description of
org.eclipse.gef3d.ext.intermodel for details.
Cheers,
Jens
[Updated on: Fri, 03 February 2012 12:23] Report message to a moderator
|
|
|
Re: ClassCastException on extended InterModelDiagramFigure [message #789799 is a reply to message #789041] |
Fri, 03 February 2012 12:22 |
Lukas Olbrich Messages: 17 Registered: October 2010 |
Junior Member |
|
|
Hi everyone,
I see, that my problem mainly occurs from the lack of knowledge concerning the creation of InterModelConnections.
I just cannot see the way of how to add them to my multi-editor.
My Idea is the following:
Add an editor for each diagramm: works totally fine.
Now, add a model-Object to the MultiEditorContainer that is capable of returning the InterModelConnections as Children. Register this ModelObject (e.g. InterModelConnectionsContainer) within the MultiFactory by calling prepare. Does not work.
I found this in the graph-example of GEF3D. It's exactly what I meant to do.
IntermodelContainer intermodel = new IntermodelContainer();
IntermodelEditPartFactory intermodelFactory = new IntermodelEditPartFactory();
multiFactory.prepare(intermodel, intermodelFactory);
I noticed that commenting the last line does not change the Editors behaviour. All InterConnections are drawn correctly. Thus, the InterModelContainer object does not have any effect. I believe this is due to the underlying graph model. The InterModelConnections are of type Edge and can be retrieved by asking the Graph or a Node, I mean, they're part of the moldel, thus they are most probably returned by a NodeEditPart as connections. This would explain, why intermodelConnections are drawn. This is due to:
multiFactory.prepare(graphs[p], intermodelFactory, MultiEditorPartFactory.HIGHEST_PRIORITY);
For a Graph the interModelFactory is also registered, especially with highest priority. Thus, this factory will always be called first and checks whether the given edge is an InterModelConnection. Thus, the interModelConnections as well as the different models are actually all part of the same model. They are one.
My case is different: I have different editors for different graphs represtenting different models. The nodes of my graph do not return the intermodelconnections as connections. Thus, these connections are never drawn.
This leads to the question of how to add a dummy model object to the MultiEditorModelContainer? If I prepare a dummy object for this, either I get an ArrayOutOfBounds or a ClassCastEx. This depends on the EditPart I create for my InterModelConnectionsContainer.
I would really appreciate any explanation of how to properly add a dummy model object that represents my InterModelConnections to the scene.
Thanks very much,
Lukas
[Updated on: Fri, 03 February 2012 12:25] Report message to a moderator
|
|
|
Re: ClassCastException on extended InterModelDiagramFigure [message #789810 is a reply to message #789799] |
Fri, 03 February 2012 12:36 |
|
Lukas,
our last comments just overlapped. The graph example actually isn't the best example for real inter model connections. In the Eclipse Magazin article, I distinguish between so called inter diagram connections (IDC) and inter model connections (IMC). An IDC is (in case of GEF3D) a 3D connection between elements displayed on different planes, but all elements (the connected nodes and the connection) are part of the same model. That is, all these elements "know" each other. An IMC usually is a kind of IDC, but the connection does not belong to the same model as the connected nodes. This is true for your case.
In the graph example, the connections between different graphs are actually stored in a separate model (the IntermodelContainer), but since they are of the same type as the "normal" edges, they are much easier to handle (as the connected nodes can handle them correctly). I think we have to modify the graph example or provide an extra inter model example. However, the example described in the article comes with real IMCs, that is the markers are connected to model elements, and these elements do not know anything about the markers. Note that the marker example of the article assumes that the edit parts of the connected elements do support the markers. This is why UndirectConnectionEditPart3D could be used. If you cannot adjust these edit parts, you will have to use ConnectedElementAdapter (in which case you do not need UndirectConnectionEditPart3D anymore).
Cheers,
Jens
|
|
|
Re: ClassCastException on extended InterModelDiagramFigure [message #789817 is a reply to message #789810] |
Fri, 03 February 2012 12:50 |
Lukas Olbrich Messages: 17 Registered: October 2010 |
Junior Member |
|
|
Dear Jens,
thanks for your reply. While you answered my question, I was already writing a new post. First of all, thanks for your reply. You are totally right, my question was lacking the explanation of the MVC for my TIReferences.
Lukas Graph
Root:
M TIReferenceModel IntermodelContainer
C TIReferenceModelEditPart IntermodelContainerPart
extends AbstractGraphicalEditPart extends AbstractGraphicalEditPart
V TIReferenceModelFigure IntermodelContainerFigure
extends InterModelDiagramFigure extends InterModelDiagramFigure
Inter model/diagram connection (IMC)
M TIReference Edge
C TIReferenceEditPart IntermodelEdgePart
extends UndirectConnectionEditPart3D extends AbstractConnectionEditPart3D
V TIReferenceFigure3D EdgeFigure3D
extends PolylineConnection3D extends PolylineConnection3D
The TIReferenceModelEditPart returns a List of TIReferences as modelChildren (Is this correct, since they are connections?).
Okay, in this configuration I take the following steps:
i. configure the multieditor
1. add an 3dified editor for each model - works fine.
2. create the TIReferenceModel
3. prepare the MultiEditorFactory with a factory for my controllers of the intermodelconnections.
4. add the TIReferennceModel to the MultiEditorModelContainer
The last step leads to the stacktrace listed below.
Thanks a lot,
Lukas
the object it occurs in is of type TIReferenceModelFigure.
java.lang.IndexOutOfBoundsException: Index does not exist
at org.eclipse.draw2d.Figure.add(Figure.java:139)
at org.eclipse.draw3d.Figure3D.add(Figure3D.java:198)
at org.eclipse.draw2d.Figure.add(Figure.java:184)
at org.eclipse.gef.editparts.AbstractGraphicalEditPart.addChildVisual(AbstractGraphicalEditPart.java:209)
at org.eclipse.gef.editparts.AbstractEditPart.addChild(AbstractEditPart.java:210)
at org.eclipse.gef.editparts.AbstractEditPart.refreshChildren(AbstractEditPart.java:773)
at org.eclipse.gef.editparts.AbstractEditPart.refresh(AbstractEditPart.java:718)
at org.eclipse.gef.editparts.AbstractGraphicalEditPart.refresh(AbstractGraphicalEditPart.java:633)
at org.eclipse.gef.editparts.AbstractEditPart.addNotify(AbstractEditPart.java:252)
at org.eclipse.gef.editparts.AbstractGraphicalEditPart.addNotify(AbstractGraphicalEditPart.java:223)
at org.eclipse.gef.editparts.AbstractEditPart.addChild(AbstractEditPart.java:211)
at org.eclipse.gef3d.ext.multieditor.MultiEditorModelContainerEditPart.propertyChange(MultiEditorModelContainerEditPart.java:149)
at java.beans.PropertyChangeSupport.firePropertyChange(PropertyChangeSupport.java:339)
at java.beans.PropertyChangeSupport.firePropertyChange(PropertyChangeSupport.java:276)
at org.eclipse.gef3d.ext.multieditor.MultiEditorModelContainer.add(MultiEditorModelContainer.java:86)
at de.bitub.proitbau.core.ui.ti.process.gef3d.TIProcessGEFMultiEditor3D.initialiseDiagram(TIProcessGEFMultiEditor3D.java:47)
at de.bitub.proitbau.core.ui.ti.process.gef3d.TIProcessGEFMultiEditor3D.initializeGraphicalViewer(TIProcessGEFMultiEditor3D.java:104)
at org.eclipse.gef3d.ui.parts.GraphicalEditor3DWithFlyoutPalette.createGraphicalViewer(GraphicalEditor3DWithFlyoutPalette.java:67)
at org.eclipse.gef.ui.parts.GraphicalEditor.createPartControl(GraphicalEditor.java:171)
at org.eclipse.gef.ui.parts.GraphicalEditorWithFlyoutPalette.createPartControl(GraphicalEditorWithFlyoutPalette.java:75)
at org.eclipse.ui.internal.EditorReference.createPartHelper(EditorReference.java:670)
at org.eclipse.ui.internal.EditorReference.createPart(EditorReference.java:465)
at org.eclipse.ui.internal.WorkbenchPartReference.getPart(WorkbenchPartReference.java:595)
at org.eclipse.ui.internal.PartPane.setVisible(PartPane.java:313)
at org.eclipse.ui.internal.presentations.PresentablePart.setVisible(PresentablePart.java:180)
at org.eclipse.ui.internal.presentations.util.PresentablePartFolder.select(PresentablePartFolder.java:270)
at org.eclipse.ui.internal.presentations.util.LeftToRightTabOrder.select(LeftToRightTabOrder.java:65)
at org.eclipse.ui.internal.presentations.util.TabbedStackPresentation.selectPart(TabbedStackPresentation.java:473)
at org.eclipse.ui.internal.PartStack.refreshPresentationSelection(PartStack.java:1254)
at org.eclipse.ui.internal.PartStack.setSelection(PartStack.java:1207)
at org.eclipse.ui.internal.PartStack.showPart(PartStack.java:1606)
at org.eclipse.ui.internal.PartStack.add(PartStack.java:497)
at org.eclipse.ui.internal.EditorStack.add(EditorStack.java:103)
at org.eclipse.ui.internal.PartStack.add(PartStack.java:483)
at org.eclipse.ui.internal.EditorStack.add(EditorStack.java:112)
at org.eclipse.ui.internal.EditorSashContainer.addEditor(EditorSashContainer.java:63)
at org.eclipse.ui.internal.EditorAreaHelper.addToLayout(EditorAreaHelper.java:225)
at org.eclipse.ui.internal.EditorAreaHelper.addEditor(EditorAreaHelper.java:213)
at org.eclipse.ui.internal.EditorManager.createEditorTab(EditorManager.java:778)
at org.eclipse.ui.internal.EditorManager.openEditorFromDescriptor(EditorManager.java:677)
at org.eclipse.ui.internal.EditorManager.openEditor(EditorManager.java:638)
at org.eclipse.ui.internal.WorkbenchPage.busyOpenEditorBatched(WorkbenchPage.java:2860)
at org.eclipse.ui.internal.WorkbenchPage.busyOpenEditor(WorkbenchPage.java:2768)
at org.eclipse.ui.internal.WorkbenchPage.access$11(WorkbenchPage.java:2760)
at org.eclipse.ui.internal.WorkbenchPage$10.run(WorkbenchPage.java:2711)
at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:70)
at org.eclipse.ui.internal.WorkbenchPage.openEditor(WorkbenchPage.java:2707)
at org.eclipse.ui.internal.WorkbenchPage.openEditor(WorkbenchPage.java:2691)
at org.eclipse.ui.internal.WorkbenchPage.openEditor(WorkbenchPage.java:2674)
at de.bitub.proitbau.core.ui.ti.process.internal.OpenGEF3DEditorHandler.execute(OpenGEF3DEditorHandler.java:46)
at org.eclipse.ui.internal.handlers.HandlerProxy.execute(HandlerProxy.java:293)
at org.eclipse.core.commands.Command.executeWithChecks(Command.java:476)
at org.eclipse.core.commands.ParameterizedCommand.executeWithChecks(ParameterizedCommand.java:508)
at org.eclipse.ui.internal.handlers.HandlerService.executeCommand(HandlerService.java:169)
at org.eclipse.ui.internal.handlers.SlaveHandlerService.executeCommand(SlaveHandlerService.java:241)
at org.eclipse.ui.internal.handlers.SlaveHandlerService.executeCommand(SlaveHandlerService.java:241)
at org.eclipse.ui.menus.CommandContributionItem.handleWidgetSelection(CommandContributionItem.java:820)
at org.eclipse.ui.menus.CommandContributionItem.access$19(CommandContributionItem.java:806)
at org.eclipse.ui.menus.CommandContributionItem$5.handleEvent(CommandContributionItem.java:796)
at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1053)
at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:4066)
at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3657)
at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2640)
at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2604)
at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2438)
at org.eclipse.ui.internal.Workbench$7.run(Workbench.java:671)
at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:664)
at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149)
at de.bitub.proitbau.app.main.Application.start(Application.java:22)
at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:369)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:620)
at org.eclipse.equinox.launcher.Main.basicRun(Main.java:575)
at org.eclipse.equinox.launcher.Main.run(Main.java:1408)
at org.eclipse.equinox.launcher.Main.main(Main.java:1384)
[Updated on: Fri, 03 February 2012 13:10] Report message to a moderator
|
|
| |
Re: ClassCastException on extended InterModelDiagramFigure [message #789893 is a reply to message #789817] |
Fri, 03 February 2012 14:45 |
|
Dear Lukas,
frankly, I haven't much time to look into that much deeper now. Well,
getModelChildren() is supposed to return the model children, and as far
as I can tell there is nothing stopping you from returning connections.
However, the GEF mechanism of actually gluing connections to the nodes
is a little bit weird: Let's say a model connection c_m is connecting
model node ns_m (node source) with nt_m (node target). Let's further say
c_ep, ns_ep, and nt_ep are the edit parts for these elements. Now, how
does it work with GEF:
Assume, ns_ep and ns_ep are already created and connected to their
models. I start with the source node, but source or target node can be
exchanged:
1) ns_ep.refreshSourceConnections() is called by some refresh mechanism
2) this calls ns_ep.getModelSourceConnections(), returning c_m
3) edit part c_ep for c_m is created (via the factory)4
4) c_ep's source is set to ns_ep.
At this point, although c_ep exists, it's figure is not created or drawn
-- for GEF, the connection is dangling wihout a target at the moment
(see AbstractConnectionEditPart.setSource/Target(EditPart)). Later on
(caused by the initial refresh or some other update mechanism), the
following happens:
5) nt_ep.refreshTragetConnections() is called
6) this calls nt_ep.getModelSourceConnections(), returning c_m
7) c_ep is not created again, but found
(see IFigure.createOrFindConnection()).
8) c_ep's target is set to nt_ep
Now, the connection edit part has source and target set, and the figure
can be drawn.
IMHO this is a design bug, as it's not the connection responsible for
gathering its source and target edit parts, but the source and target
edit parts are responsible for registering themselves to the connection.
This becomes a problem with unidirectional connections.
The UndirectConnectionEditPart3D behaves differently. While
AbstractConnectionEditPart.getSource/Target() are pure getters,
UndirectConnectionEditPart3D.getSource/Target() can resolve the edit
parts if necessary. This way, the node edit parts does not have to know
anything about the connection. And this is why you can return models
managed by UndirectConnectionEditPart3D in getModelChildren().
Again, this only works as long as the node edit parts can create an
anchor for your 3D connection in
NodeEditPart.getSource/TargetConnectionAnchor(). If your nodes cannot
created anchors for UndirectConnectionEditPart3D, you cannot use the
later. In that case, you will have to use the ConnectedElementAdapter
pattern provided by GEF3D. In that case you do not have to use the
UndirectConnectionEditPart3D. The adapter pattern basically creates
invisible nodes attaching themselves to the source and target node.
Then, the connection is a standard GEF connection, connecting these
little invisible adapters (instead of the real nodes). Since the
adapters are fully aware of the connection, you can use the standard GEF
mechanism as described above.
Cheers,
Jens
P.S.: If you have a working example, stripped down to inter model
connections, it would be great to make this available to others. I'm
looking forward to it.
|
|
| | | |
Goto Forum:
Current Time: Fri Mar 29 01:20:34 GMT 2024
Powered by FUDForum. Page generated in 0.02845 seconds
|