Graphiti and GMF Compared
-
Upload
koentsje -
Category
Technology
-
view
8.887 -
download
2
Transcript of Graphiti and GMF Compared
© 2011 by Koen Aers; made available under the EPL v1.0Graphiti and GMF Compared : Revisiting the Graph Editor1
Graphiti and GMF Compared
The Graph Editor Revisited
Koen Aers
© 2011 by Koen Aers; made available under the EPL v1.0Graphiti and GMF Compared : Revisiting the Graph Editor2
Speaker
JBoss Tools: http://www.jboss.org/tools Email: [email protected] Blog:
http://community.jboss.org/people/koen.aers/blog
http://koentsje.blogspot.com/
© 2011 by Koen Aers; made available under the EPL v1.0Graphiti and GMF Compared : Revisiting the Graph Editor3
Agenda
Introduction : Graphiti and GMF Graph Editor: GEF Memories Common Foundation : Graph EMF Model Generating a Graph Editor : GMF Tools Handcrafting a Graph Editor
Part 1 : Graphiti
Part 2 : the GMF Runtime
Graphiti and GMF Compared Conclusion
© 2011 by Koen Aers; made available under the EPL v1.0Graphiti and GMF Compared : Revisiting the Graph Editor4
Graphiti and GMF
Frameworks to create rich graphical editors easily Part of the Graphical Modeling Platform GMF:
Around @ Eclipse since 2005
Runtime (IBM) & Tools part (Borland R.I.P)
Graphiti Initial contribution March 2010 (currently incubating)
Main backing company: SAP
`Separation of semantic graphical information Stored either separately or together
© 2011 by Koen Aers; made available under the EPL v1.0Graphiti and GMF Compared : Revisiting the Graph Editor5
GEF Memories
22 Java classes 1023 lines of code 17 lines of plugin.xml No persistence No alignment, popup
bars, zoom, etc. Comprehensive
understanding of the framework
© 2011 by Koen Aers; made available under the EPL v1.0Graphiti and GMF Compared : Revisiting the Graph Editor6
An EMF Model For Graphs<grph:graph xmlns:grph="http://www.graph.org/model" id="0" name="Base"> <grph:node id="1" name="f"/> <grph:node id="2" name="s"/> <grph:edge id="3" name="e" from="1 to="2"/></grph:graph>
<xsd:schema ...> <xsd:complexType name="Base" ...> <xsd:attribute name="id" .../> <xsd:attribute name="name" .../> </xsd:complexType> <xsd:complexType name="Node"> <xsd:complexContent> <xsd:extension base="Base"/> </xsd:complexContent> </xsd:complexType> <xsd:complexType name="Edge"> <xsd:complexContent> <xsd:extension base="Base"> <xsd:attribute name="from" .../> <xsd:attribute name="to" .../> </xsd:extension> </xsd:complexContent> </xsd:complexType> <xsd:complexType name="Graph"> ... </xsd:complexType> <xsd:element name="graph" type="Graph"/></xsd:schema>
© 2011 by Koen Aers; made available under the EPL v1.0Graphiti and GMF Compared : Revisiting the Graph Editor7
GMF Tools: Overview
© 2011 by Koen Aers; made available under the EPL v1.0Graphiti and GMF Compared : Revisiting the Graph Editor8
GMF Tools : Generate a Graph Editor
Use GMF dashboard Select domain model Select domain gen model Derive GMF graph model Derive GMF tool model Combine into GMF
mapping model
Transform into GMF generator model
Generate Graph Editor
© 2011 by Koen Aers; made available under the EPL v1.0Graphiti and GMF Compared : Revisiting the Graph Editor9
Graphiti: Overview
© 2011 by Koen Aers; made available under the EPL v1.0Graphiti and GMF Compared : Revisiting the Graph Editor10
Handcrafting a Graph Editor with Graphiti
Plugin project + dependencies Contribute the Editor Contribute the Diagram Type and Diagram Type
Provider Create a Feature Provider Contribute a wizard to create graphs Add the features to the Feature Provider
CreateNodeFeature, AddNodeFeature
CreateEdgeFeature, AddEdgeFeature
Contribute the property page to edit the attributes
© 2011 by Koen Aers; made available under the EPL v1.0Graphiti and GMF Compared : Revisiting the Graph Editor11
Graphiti : First Steps
Create plugin project Add dependencies Contribute editor Contribute diagram type Contribute diagram type
provider
<plugin> <extension point="org.eclipse.ui.editors"> <editor class="org.eclipse.graphiti.ui.editor.DiagramEditor" default="false" extensions="graphiti_diagram" id="org.graph.graphiti.diagram.editor" name="Graphiti Graph Editor"/> </extension> <extension point="org.eclipse.graphiti.ui.diagramTypes"> <diagramType id="org.graph.graphiti.diagram" name="Graph Diagram" type="org.graph.graphiti.diagram"/> </extension> <extension point="org.eclipse.graphiti.ui.diagramTypeProviders"> <diagramTypeProvider class="org.graph....GraphDiagramTypeProvider" id="org.graph.graphiti.diagram" name="Graph Editor"> <diagramType id="org.graph.graphiti.diagram"/> </diagramTypeProvider> </extension></plugin>
Require-Bundle: org.eclipse.ui, org.eclipse.core.runtime, org.eclipse.graphiti, org.eclipse.graphiti.ui, org.graph.emf, org.eclipse.ui.views.properties.tabbed, org.eclipse.ui.ide, org.eclipse.core.resources, org.eclipse.emf.transaction
© 2011 by Koen Aers; made available under the EPL v1.0Graphiti and GMF Compared : Revisiting the Graph Editor12
Graphiti : Diagram Type and Feature Provider
public class GraphDiagramTypeProvider extends AbstractDiagramTypeProvider {
public static final String DIAGRAM_TYPE_ID = "org.graph.graphiti.diagram"; public static final String PROVIDER_ID = "org.graph.graphiti.diagram";
public GraphDiagramTypeProvider() { super(); setFeatureProvider(new GraphDiagramFeatureProvider(this)); }
}
public class GraphDiagramFeatureProvider extends DefaultFeatureProvider {
public GraphDiagramFeatureProvider(IDiagramTypeProvider dtp) { super(dtp); }
}
© 2011 by Koen Aers; made available under the EPL v1.0Graphiti and GMF Compared : Revisiting the Graph Editor13
Graphiti : Create a Graph<plugin> ... <extension point="org.eclipse.ui.newWizards"> <category id="org.graph.graphiti.diagram" name="Graph"/> <wizard category="org.graph.graphiti.diagram" class="org.graph...GraphCreationWizard" id="org.graph.graphiti.diagram.wizard" name="Graphiti Graph"/> </extension></plugin>
Semantic and graphic info stored separately No ready to use wizards available Mainly EMF related object manipulations
© 2011 by Koen Aers; made available under the EPL v1.0Graphiti and GMF Compared : Revisiting the Graph Editor14
public static Resource createDiagram(URI d, URI m, IProgressMonitor pm) { TransactionalEditingDomain ed = DiagramEditorFactory.createResourceSetAndEditingDomain(); final Resource dr = ed.getResourceSet().createResource(d); final Resource mr = ed.getResourceSet().createResource(m); final Graph model = GraphFactory.eINSTANCE.createGraph(); final DocumentRoot documentRoot = GraphFactory.eINSTANCE.createDocumentRoot(); documentRoot.setGraph(model); String diagramName = d.lastSegment(); final Diagram diagram = Graphiti.getPeCreateService().createDiagram(
GraphDiagramTypeProvider.DIAGRAM_TYPE_ID, diagramName, true); PictogramLink link = PictogramsFactory.eINSTANCE.createPictogramLink(); diagram.setLink(link); link.getBusinessObjects().add(model); final CommandStack commandStack = ed.getCommandStack(); commandStack.execute(new RecordingCommand(ed) { protected void doExecute() { mr.setTrackingModification(true); dr.setTrackingModification(true); dr.getContents().add(diagram); mr.getContents().add(documentRoot); try { mr.save(Collections.EMPTY_MAP); dr.save(Collections.EMPTY_MAP); } catch (IOException e) {} } }); return dr;}
© 2011 by Koen Aers; made available under the EPL v1.0Graphiti and GMF Compared : Revisiting the Graph Editor15
Graphiti : Create Nodes (1/2)
public class CreateNodeFeature extends AbstractCreateFeature {
public CreateNodeFeature(IFeatureProvider fp) { super(fp, "Node", "Create Node"); }
public boolean canCreate(ICreateContext context) { return context.getTargetContainer() instanceof Diagram; }
public Object[] create(ICreateContext context) { Node node = GraphFactory.eINSTANCE.createNode(); addGraphicalRepresentation(context, node); return new Object[] { node }; }
}
© 2011 by Koen Aers; made available under the EPL v1.0Graphiti and GMF Compared : Revisiting the Graph Editor16
Graphiti : Create Nodes (2/2)
public class GraphDiagramFeatureProvider extends DefaultFeatureProvider {
...
public ICreateFeature[] getCreateFeatures() { return new ICreateFeature[] { new CreateNodeFeature(this) }; }
}
© 2011 by Koen Aers; made available under the EPL v1.0Graphiti and GMF Compared : Revisiting the Graph Editor17
Graphiti : Add Nodes (1/2)public class AddNodeFeature extends AbstractAddShapeFeature {
public AddNodeFeature(IFeatureProvider fp) { super(fp); }
public boolean canAdd(IAddContext context) { return ((context.getNewObject() instanceof Node) && (context.getTargetContainer() instanceof Diagram)); }
public PictogramElement add(IAddContext context) { Diagram targetDiagram = (Diagram)context.getTargetContainer(); Graph graph = (Graph)targetDiagram.getLink().getBusinessObjects().get(0); graph.getNode().add((Node)context.getNewObject()); ContainerShape cs = Graphiti.getPeCreateService().createContainerShape(targetDiagram, true); RoundedRectangle rr = Graphiti.getGaService().createRoundedRectangle(cs, 8, 8); rr.setFilled(false); Graphiti.getGaService().setLocationAndSize(rr, context.getX(), context.getY(), 80, 40); link(cs, (Node)context.getNewObject()); layoutPictogramElement(cs); return cs; }
}
© 2011 by Koen Aers; made available under the EPL v1.0Graphiti and GMF Compared : Revisiting the Graph Editor18
Graphiti : Add Nodes (2/2)
public class GraphDiagramFeatureProvider extends DefaultFeatureProvider {
...
public IAddFeature getAddFeature(IAddContext context) { if (context.getNewObject() instanceof Node) { return new AddNodeFeature(this); } return super.getAddFeature(context); }
}
© 2011 by Koen Aers; made available under the EPL v1.0Graphiti and GMF Compared : Revisiting the Graph Editor19
Graphiti : Create Edges (1/3)public class CreateEdgeFeature extends AbstractCreateConnectionFeature {
public CreateEdgeFeature(IFeatureProvider fp) { super(fp, "Edge", "Create Edge"); }
public boolean canCreate(ICreateConnectionContext context) { return (getNode(context.getSourceAnchor()) != null) && (getNode(context.getTargetAnchor()) != null); }
private Node getNode(Anchor anchor) { if (anchor == null) return null; Object object = getBusinessObjectForPictogramElement(anchor.getParent()); if (object instanceof Node) return (Node)object; return null; }
public boolean canStartConnection(ICreateConnectionContext context) { return getNode(context.getSourceAnchor()) != null; }
...
© 2011 by Koen Aers; made available under the EPL v1.0Graphiti and GMF Compared : Revisiting the Graph Editor20
Graphiti : Create Edges (2/3) ...
public Connection create(ICreateConnectionContext context) { Edge edge = GraphFactory.eINSTANCE.createEdge(); edge.setFrom(getNode(context.getSourceAnchor())); edge.setTo(getNode(context.getTargetAnchor())); Graph graph = (Graph)getDiagram().getLink().getBusinessObjects().get(0); graph.getEdge().add(edge); AddConnectionContext addConnectionContext = new AddConnectionContext(context.getSourceAnchor(), context.getTargetAnchor()); addConnectionContext.setNewObject(edge); return (Connection)getFeatureProvider().addIfPossible(addConnectionContext); }
}
public class GraphDiagramFeatureProvider extends DefaultFeatureProvider {
...
public ICreateConnectionFeature[] getCreateConnectionFeatures() { return new ICreateConnectionFeature[] { new CreateEdgeFeature(this) }; }
}
© 2011 by Koen Aers; made available under the EPL v1.0Graphiti and GMF Compared : Revisiting the Graph Editor21
Graphiti : Create Edges (3/3)
public class GraphDiagramFeatureProvider extends DefaultFeatureProvider {
...
public ICreateConnectionFeature[] getCreateConnectionFeatures() { return new ICreateConnectionFeature[] { new CreateEdgeFeature(this) }; }
}
public class AddNodeFeature extends AbstractAddShapeFeature {
...
public PictogramElement add(IAddContext context) { ... getPeCreateService().createChopboxAnchor(cs);; return cs; }
}
© 2011 by Koen Aers; made available under the EPL v1.0Graphiti and GMF Compared : Revisiting the Graph Editor22
Graphiti : Add Edges (1/2)public class AddEdgeFeature extends AbstractAddFeature {
public AddEdgeFeature(IFeatureProvider fp) { super(fp); }
public boolean canAdd(IAddContext context) { return context instanceof IAddConnectionContext && context.getNewObject() instanceof Edge); }
public PictogramElement add(IAddContext context) { IAddConnectionContext addConnectionContext = (IAddConnectionContext)context; Edge addedEdge = (Edge)context.getNewObject(); IPeCreateService peCreateService = Graphiti.getPeCreateService(); Connection connection = peCreateService.createFreeFormConnection(getDiagram()); connection.setStart(addConnectionContext.getSourceAnchor()); connection.setEnd(addConnectionContext.getTargetAnchor()); IGaService gaService = Graphiti.getGaService(); gaService.createPolyline(connection); link(connection, addedEdge); return connection; }
}
© 2011 by Koen Aers; made available under the EPL v1.0Graphiti and GMF Compared : Revisiting the Graph Editor23
Graphiti : Add Edges (2/2)
public class GraphDiagramFeatureProvider extends DefaultFeatureProvider {
...
public IAddFeature getAddFeature(IAddContext context) { if (context.getNewObject() instanceof Node) { return new AddNodeFeature(this); } else if (context.getNewObject() instanceof Edge) { return new AddEdgeFeature(this); } return super.getAddFeature(context); }
}
© 2011 by Koen Aers; made available under the EPL v1.0Graphiti and GMF Compared : Revisiting the Graph Editor24
Graphiti : Simple Graph Editor
© 2011 by Koen Aers; made available under the EPL v1.0Graphiti and GMF Compared : Revisiting the Graph Editor25
Handcrafting a Graph Editor with GMF
Create plugin + dependencies
Contribute The Editor
The Element Types
The View Provider
Contribute and implement a wizard to create graphs
Contribute the Palette Provider and implement a PaletteFactory
Implement NodeEditPart & EdgeEditPart
Add the NodeEditHelper Add the
DocumentProvider to enable saving
Add the ActionBarContributor
Add the Properties Page
© 2011 by Koen Aers; made available under the EPL v1.0Graphiti and GMF Compared : Revisiting the Graph Editor26
GMF Runtime : First Steps
Create plugin project Add dependencies Contribute editor Contribute element types Contribute view provider
<plugin> <extension point="org.eclipse.ui.editors"> <editor class="org.eclipse.gmf.runtime.diagram.ui...ide.editor.FileDiagramEditorWithFlyoutPalette" default="false" extensions="gmf_runtime_diagram" id="org.graph.gmf.runtime.diagram.editor" name="GMF Runtime Graph Editor"/> </extension></plugin>
Require-Bundle: org.eclipse.ui, org.eclipse.core.runtime, org.eclipse.core.resources, org.eclipse.ui.ide, org.eclipse.gmf.runtime.diagram.ui, org.eclipse.gmf.runtime.diagram.ui.resources.editor.ide, org.eclipse.gmf.runtime.diagram.ui.providers, org.graph.emf
© 2011 by Koen Aers; made available under the EPL v1.0Graphiti and GMF Compared : Revisiting the Graph Editor27
GMF Runtime : Element Types<plugin> ... <extension point="org.eclipse.gmf.runtime.emf.type.core.elementTypes"> <metamodel nsURI="http://www.graph.org/model"> <metamodelType id="org.graph.gmf.runtime.graph" eclass="Graph" kind="org.eclipse.gmf.runtime.emf.type.core.IHintedType" name="Graph"> <param name="semanticHint"value="org.graph.gmf.runtime.graph"/> </metamodelType> <metamodelType id="org.graph.gmf.runtime.node" name="Node" eclass="Node" kind="org.eclipse.gmf.runtime.emf.type.core.IHintedType"> <param name="semanticHint" value="org.graph.gmf.runtime.node"/> </metamodelType> <metamodelType id="org.graph.gmf.runtime.edge" name="Edge" eclass="Edge" kind="org.eclipse.gmf.runtime.emf.type.core.IHintedType"> <param name="semanticHint" value="org.graph.gmf.runtime.edge"/> </metamodelType> </metamodel> </extension></plugin>
© 2011 by Koen Aers; made available under the EPL v1.0Graphiti and GMF Compared : Revisiting the Graph Editor28
GMF Runtime : View Provider <extension point="org.eclipse.gmf.runtime.diagram.core.viewProviders"> <viewProvider class="org.graph.gmf.runtime.diagram.providers.GraphViewProvider"> <Priority name="Lowest"/> <context viewClass="org.eclipse.gmf.runtime.notation.Diagram" semanticHints="org.graph.gmf.runtime.graph"/> <context viewClass="org.eclipse.gmf.runtime.notation.Node" semanticHints="org.graph.gmf.runtime.node"/> <context viewClass="org.eclipse.gmf.runtime.notation.Edge" semanticHints="org.graph.gmf.runtime.edge"/> </viewProvider> </extension>
public class GraphViewProvider extends AbstractViewProvider { protected Class getDiagramViewClass(IAdaptable semanticAdapter, String dk) { return "org.graph.gmf.runtime.graph".equals(dk) ? StandardDiagramViewFactory.class : null; } protected Class getNodeViewClass(IAdaptable semanticAdapter, View containerView, String sh) { return "org.graph.gmf.runtime.node".equals(sh) ? ShapeViewFactory.class : null; } protected Class getEdgeViewClass(IAdaptable semanticAdapter, View containerView, String sh) { return "org.graph.gmf.runtime.edge".equals(sh) ? ConnectionViewFactory.class : null; }}
© 2011 by Koen Aers; made available under the EPL v1.0Graphiti and GMF Compared : Revisiting the Graph Editor29
GMF Runtime : Create a Graph (1/4)
public class GraphCreationWizard extends EditorCreationWizard{ public void addPages() { addPage(page = new GraphCreationWizardPage(getWorkbench(), getSelection())); }
public void init(IWorkbench workbench, IStructuredSelection sel) { super.init(workbench, sel); }
}
<plugin> ... <extension point="org.eclipse.ui.newWizards"> <category id="org.graph.gmf.runtime.diagram" name="Graph GMF Runtime"> </category> <wizard category="org.graph.gmf.runtime.diagram" class="org.graph.gmf.runtime.diagram.wizard.GraphCreationWizard" id="org.graph.gmf.runtime.diagram.wizard" name="Graph"> </wizard> </extension></plugin>
© 2011 by Koen Aers; made available under the EPL v1.0Graphiti and GMF Compared : Revisiting the Graph Editor30
GMF Runtime : Create a Graph (2/4)public class GraphCreationWizardPage extends EditorWizardPage {
private IDEEditorFileCreator dfc = null;
public GraphCreationWizardPage(IWorkbench aWorkbench, IStructuredSelection selection) { super("GraphDiagramPage", aWorkbench, selection); setTitle("Create Graph Diagram"); setDescription("Create a new Graph diagram."); }
public DiagramFileCreator getDiagramFileCreator() { if (dfc == null) dfc = new IDEEditorFileCreator() { public String getExtension() { return ".gmf_runtime_diagram"; } } return dfc; }
protected String getDefaultFileName() { return "default"; } protected String getDiagramKind() { return "org.graph.gmf.runtime.graph"; }
public IFile createAndOpenDiagram(IPath cp, String fn, InputStream ic, String k, IWorkbenchWindow ww, IProgressMonitor pm, boolean sd) { String srp = cp.append(fn).removeFileExtension().addFileExtension("graph").toString(); return GraphDiagramEditorUtil.createAndOpenDiagram(dfc, cp, fn, ic, k, ww, pm, srp); }}
© 2011 by Koen Aers; made available under the EPL v1.0Graphiti and GMF Compared : Revisiting the Graph Editor31
GMF Runtime : Create a Graph (3/4)
public class GraphDiagramEditorUtil {
public static IFile createAndOpenDiagram(DiagramFileCreator dfc, IPath cp, String fn, InputStream ic, String k, IWorkbenchWindow ww, IProgressMonitor pm, String srp) { IFile newFile = createNewDiagramFile(dfc, cp, fn, ic, k, ww.getShell(), pm, srp); if (newFile != null) { IDEEditorUtil.openDiagram(newFile, ww, true, pm); } return newFile; }
public static IFile createNewDiagramFile(DiagramFileCreator dfc, IPath cfp, String fn, InputStream ic, String k, Shell s, IProgressMonitor pm, final String srp) { IFile newDiagramFile = dfc.createNewFile(cfp, fn, ic, s, new WorkspaceOperationRunner()); TransactionalEditingDomain domain = GMFEditingDomainFactory.getInstance().createEditingDomain(); AbstractEMFOperation op = new GraphDiagramCreationOperation(newDiagramFile, srp, domain, k); try { op.execute(new NullProgressMonitor(), null); } catch (ExecutionException e) {} return newDiagramFile; }
}
© 2011 by Koen Aers; made available under the EPL v1.0Graphiti and GMF Compared : Revisiting the Graph Editor32
GMF Runtime : Create a Graph (4/4)public class GraphDiagramCreationOperation extends AbstractEMFOperation { private IFile ndf; private String dk, srp; public GraphDiagramCreationOperation(IFile ndf, String srp, TransactionalEditingDomain ed, String dk) { super(ed, "Create Graph Diagram"); this.ndf = ndf; this.dk = dk; this.srp = srp; } protected IStatus doExecute(IProgressMonitor pm, IAdaptable adaptable) throws ExecutionException { DocumentRoot documentRoot = GraphFactory.eINSTANCE.createDocumentRoot(); documentRoot.setGraph(GraphFactory.eINSTANCE.createGraph()); ResourceSet resourceSet = getEditingDomain().getResourceSet(); Resource semanticResource = resourceSet.createResource(URI.createPlatformResourceURI(srp, true)); semanticResource.getContents().add(documentRoot); String completeFileName = ndf.getLocation().toOSString(); Resource notationResource = resourceSet.createResource(URI.createFileURI(completeFileName)); Diagram view = ViewService.createDiagram(dk, new PreferencesHint("org.graph.gmf.runtime.diagram"));
notationResource.getContents().add(view); view.setName(ndf.getName()); view.setElement(documentRoot.getGraph()); try { semanticResource.save(Collections.EMPTY_MAP); notationResource.save(Collections.EMPTY_MAP); } catch (IOException e) {} return Status.OK_STATUS; }}
© 2011 by Koen Aers; made available under the EPL v1.0Graphiti and GMF Compared : Revisiting the Graph Editor33
GMF Runtime : Palette Provider (1/2) <extension point="org.eclipse.gmf.runtime.diagram.ui.paletteProviders"> <paletteProvider class="org.eclipse.gmf.runtime.diagram.ui.providers.DefaultPaletteProvider"> <Priority name="Lowest"/> <editor id="org.graph.gmf.runtime.diagram.editor"/> <contribution factoryClass="org.graph.gmf.runtime.diagram.providers.GraphPaletteFactory"> <entry label="Graph" kind="drawer" path="/" id="org.graph.gmf.runtime.graph"> <expand><content/></expand> </entry> <entry label="Node" kind="tool" id="org.graph.gmf.runtime.node" path="/org.graph.gmf.runtime.graph/"/> <entry label="Edge" kind="tool" id="org.graph.gmf.runtime.edge" path="/org.graph.gmf.runtime.graph/"/> </contribution> </paletteProvider> </extension>
© 2011 by Koen Aers; made available under the EPL v1.0Graphiti and GMF Compared : Revisiting the Graph Editor34
GMF Runtime : Palette Provider (2/2)public class GraphPaletteFactory extends PaletteFactory.Adapter {
public Tool createTool(String toolId) { if ("org.graph.gmf.runtime.node".equals(toolId)) { return new CreationTool(ElementTypeRegistry.getInstance().getType(toolId)); } else if ("org.graph.gmf.runtime.edge".equals(toolId)) { return new ConnectionCreationTool(ElementTypeRegistry.getInstance().getType(toolId)); } return null; }
}
© 2011 by Koen Aers; made available under the EPL v1.0Graphiti and GMF Compared : Revisiting the Graph Editor35
GMF Runtime : EditPart Provider<plugin> ... <extension point="org.eclipse.gmf.runtime.diagram.ui.editpartProviders"> <editpartProvider class="org.graph.gmf.runtime.diagram.providers.GraphEditPartProvider"> <Priority name="Lowest"/> </editpartProvider> </extension> </plugin>
public class GraphEditPartProvider extends AbstractEditPartProvider {
protected Class getDiagramEditPartClass(View view ) { return "org.graph.gmf.runtime.graph".equals(view.getType()) ? DiagramEditPart.class : null; }
protected Class getNodeEditPartClass(View view) { return "org.graph.gmf.runtime.node".equals(view.getType()) ? NodeEditPart.class : null; }
protected Class getEdgeEditPartClass(View view) { return "org.graph.gmf.runtime.edge".equals(view.getType()) ? EdgeEditPart.class : null; }
}
© 2011 by Koen Aers; made available under the EPL v1.0Graphiti and GMF Compared : Revisiting the Graph Editor36
GMF Runtime : NodeEditPart and EdgeEditPartpublic class NodeEditPart extends ShapeNodeEditPart {
public NodeEditPart(View view) { super(view); }
protected NodeFigure createNodeFigure() { NodeFigure result = new NodeFigure(); result.setLayoutManager(new StackLayout()); result.add(new RoundedRectangle()); return result; }
}
public class EdgeEditPart extends ConnectionEditPart {
public EdgeEditPart(View view) { super(view); }
protected Connection createConnectionFigure() { return new PolylineConnection(); }
}
© 2011 by Koen Aers; made available under the EPL v1.0Graphiti and GMF Compared : Revisiting the Graph Editor37
GMF Runtime : Creating Edges (1/2)<metamodelType id="org.graph.gmf.runtime.node" name="Node" edithelper="org.graph.gmf.runtime.diagram.edithelper.NodeEditHelper" eclass="Node" kind="org.eclipse.gmf.runtime.emf.type.core.IHintedType"> <param name="semanticHint" value="org.graph.gmf.runtime.node"/></metamodelType>
public class NodeEditHelper extends AbstractEditHelper {
private static final IElementType EDGE_ELEMENT_TYPE = ElementTypeRegistry.getInstance().getType("org.graph.gmf.runtime.edge");
protected ICommand getCreateRelationshipCommand(CreateRelationshipRequest req) { if (req.getElementType() == EDGE_ELEMENT_TYPE && req.getSource() instanceof Node && req.getTarget() instanceof Node) { return new CreateEdgeCommand(req); } return super.getCreateRelationshipCommand(req); }
}
© 2011 by Koen Aers; made available under the EPL v1.0Graphiti and GMF Compared : Revisiting the Graph Editor38
GMF Runtime : Creating Edges (2/2)
public class CreateEdgeCommand extends CreateRelationshipCommand {
public CreateEdgeCommand(CreateRelationshipRequest request) { super(request); }
protected EObject getElementToEdit() { return ((Node)super.getElementToEdit()).eContainer(); }
protected EClass getEClassToEdit() { return GraphPackage.eINSTANCE.getGraph(); }
protected EReference getContainmentFeature() { return GraphPackage.eINSTANCE.getGraph_Edge(); }
}
© 2011 by Koen Aers; made available under the EPL v1.0Graphiti and GMF Compared : Revisiting the Graph Editor39
GMF Runtime : Saving the Diagram <extension point="org.eclipse.emf.ecore.extension_parser"> <parser type="gmf_runtime_diagram" class="org.eclipse.gmf.runtime.emf.core.resources.GMFResourceFactory"/> </extension> <extension point="org.eclipse.gmf.runtime.diagram.ui.resources.editor.documentProviders"> <provider class="org.graph.gmf.runtime.diagram.providers.GraphDocumentProvider" extensions="gmf_runtime_diagram" documentType="org.eclipse.gmf.runtime.diagram.ui.resources.editor.document.IDiagramDocument" id="org.graph.gmf.runtime.diagram"> </provider> </extension>
public class GraphDocumentProvider extends FileDiagramDocumentProvider { protected void saveDocumentToFile( IDocument d, IFile f, boolean o, IProgressMonitor m) throws CoreException { try { for (Resource r : ((IDiagramDocument)d).getEditingDomain().getResourceSet().getResources()) r.save(Collections.EMPTY_MAP); } catch (IOException e) {} } protected ISchedulingRule getSaveRule(Object element) { return null; }}
© 2011 by Koen Aers; made available under the EPL v1.0Graphiti and GMF Compared : Revisiting the Graph Editor40
GMF Runtime : the ActionBarContributor <extension point="org.eclipse.ui.editors"> <editor class="org...FileDiagramEditorWithFlyoutPalette" contributorClass="org.graph.gmf.runtime.diagram.GraphDiagramActionBarContributor" default="false" extensions="gmf_runtime_diagram" id="org.graph.gmf.runtime.diagram.editor" name="GMF Runtime Graph Editor"> </editor> </extension>
public class GraphDiagramActionBarContributor extends DiagramActionBarContributor {
protected String getEditorId() { return "org.graph.gmf.runtime.diagram.editor"; }
protected Class getEditorClass() { return FileDiagramEditorWithFlyoutPalette.class; }
}
© 2011 by Koen Aers; made available under the EPL v1.0Graphiti and GMF Compared : Revisiting the Graph Editor41
GMF Runtime : Simple Graph Editor
© 2011 by Koen Aers; made available under the EPL v1.0Graphiti and GMF Compared : Revisiting the Graph Editor42
Example From the Trenches : BPMN 2.0
<?xml version="1.0" encoding="UTF-8"?><bpmn2:definitions xmlns:bpmn2="..." xmlns:bpmndi="..." xmlns:dc="..." xmlns:di="..." id="d0"> <bpmn2:process id="pr1"> <bpmn2:userTask id="t1" name="task"/> </bpmn2:process> <bpmndi:BPMNDiagram id="d1"> <bpmndi:BPMNPlane id="pl1" bpmnElement="pr1"> <bpmndi:BPMNShape id="s1" bpmnElement="t1"> <dc:Bounds height="-1.0" width="-1.0" x="140.0" y="100.0"/> <bpmndi:BPMNLabel id="l1"/> </bpmndi:BPMNShape> </bpmndi:BPMNPlane> </bpmndi:BPMNDiagram></bpmn2:definitions>
© 2011 by Koen Aers; made available under the EPL v1.0Graphiti and GMF Compared : Revisiting the Graph Editor43
Example From the Trenches : BPMN 2.0
GMF Solution: Create wrapper objects for BPMNDiagram,
BPMNShape, etc from the BPMN DI EMF model project.
Wrappers implement the Diagram, Shape, etc interfaces from the GMF Graphical Notation
Make sure these wrappers are created e.g. by view provider when adding semantic objects
Graphiti: AFAICS no 'direct' way of doing this
Workaround by transforming the models when serializing/deserializing
© 2011 by Koen Aers; made available under the EPL v1.0Graphiti and GMF Compared : Revisiting the Graph Editor44
Graphiti and GMF Compared
Graphiti : Contained API (using
GEF/Draw2D)
Hides complexity at expense of flexibility
Decent documentation in form of tutorial
Low cost of entry
GMF Runtime : Extends GEF/Draw2D
Adds complexity but also functionality
Examples and documentation are available But no simple tutorials
High cost of entry
© 2011 by Koen Aers; made available under the EPL v1.0Graphiti and GMF Compared : Revisiting the Graph Editor45
Graphiti and GMF Compared
Which way do I go? GMF Tools:
Quick kickstart Easy entry to learn about the GMF Runtime Almost always continues with modifying generated code
Graphiti Quick kickstart Probably you will meet some limitations
GMF Runtime Getting started is difficult, lack of docs Complete flexibility as Draw2D and GEF is at your fingertips
=> It depends
© 2011 by Koen Aers; made available under the EPL v1.0Graphiti and GMF Compared : Revisiting the Graph Editor46
Conclusion
Implementing a graph editor has become less tedious! No GEF/Draw2D boiler plate code anymore
GMF Tools: generative approach
Graphiti: contained API using well-defined services
GMF Runtime: contributing services making use of preimplemented defaults and helpers
© 2011 by Koen Aers; made available under the EPL v1.0Graphiti and GMF Compared : Revisiting the Graph Editor47
Questions?