Top Banner
© 2011 by Koen Aers; made available under the EPL v1.0 Graphiti and GMF Compared : Revisiting the Graph Editor 1 Graphiti and GMF Compared The Graph Editor Revisited Koen Aers
47

Graphiti and GMF Compared

Jul 07, 2015

Download

Technology

koentsje
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: 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

Page 2: Graphiti and GMF Compared

© 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/

Page 3: Graphiti and GMF Compared

© 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

Page 4: Graphiti and GMF Compared

© 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

Page 5: Graphiti and GMF Compared

© 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

Page 6: Graphiti and GMF Compared

© 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>

Page 7: Graphiti and GMF Compared

© 2011 by Koen Aers; made available under the EPL v1.0Graphiti and GMF Compared : Revisiting the Graph Editor7

GMF Tools: Overview

Page 8: Graphiti and GMF Compared

© 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

Page 9: Graphiti and GMF Compared

© 2011 by Koen Aers; made available under the EPL v1.0Graphiti and GMF Compared : Revisiting the Graph Editor9

Graphiti: Overview

Page 10: Graphiti and GMF Compared

© 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

Page 11: Graphiti and GMF Compared

© 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

Page 12: Graphiti and GMF Compared

© 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); }

}

Page 13: Graphiti and GMF Compared

© 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

Page 14: Graphiti and GMF Compared

© 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;}

Page 15: Graphiti and GMF Compared

© 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 }; }

}

Page 16: Graphiti and GMF Compared

© 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) }; }

}

Page 17: Graphiti and GMF Compared

© 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; }

}

Page 18: Graphiti and GMF Compared

© 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); }

}

Page 19: Graphiti and GMF Compared

© 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; }

...

Page 20: Graphiti and GMF Compared

© 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) }; }

}

Page 21: Graphiti and GMF Compared

© 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; }

}

Page 22: Graphiti and GMF Compared

© 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; }

}

Page 23: Graphiti and GMF Compared

© 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); }

}

Page 24: Graphiti and GMF Compared

© 2011 by Koen Aers; made available under the EPL v1.0Graphiti and GMF Compared : Revisiting the Graph Editor24

Graphiti : Simple Graph Editor

Page 25: Graphiti and GMF Compared

© 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

Page 26: Graphiti and GMF Compared

© 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

Page 27: Graphiti and GMF Compared

© 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>

Page 28: Graphiti and GMF Compared

© 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; }}

Page 29: Graphiti and GMF Compared

© 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>

Page 30: Graphiti and GMF Compared

© 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); }}

Page 31: Graphiti and GMF Compared

© 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; }

}

Page 32: Graphiti and GMF Compared

© 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; }}

Page 33: Graphiti and GMF Compared

© 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>

Page 34: Graphiti and GMF Compared

© 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; }

}

Page 35: Graphiti and GMF Compared

© 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; }

}

Page 36: Graphiti and GMF Compared

© 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(); }

}

Page 37: Graphiti and GMF Compared

© 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); }

}

Page 38: Graphiti and GMF Compared

© 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(); }

}

Page 39: Graphiti and GMF Compared

© 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; }}

Page 40: Graphiti and GMF Compared

© 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; }

}

Page 41: Graphiti and GMF Compared

© 2011 by Koen Aers; made available under the EPL v1.0Graphiti and GMF Compared : Revisiting the Graph Editor41

GMF Runtime : Simple Graph Editor

Page 42: Graphiti and GMF Compared

© 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>

Page 43: Graphiti and GMF Compared

© 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

Page 44: Graphiti and GMF Compared

© 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

Page 45: Graphiti and GMF Compared

© 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

Page 46: Graphiti and GMF Compared

© 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

Page 47: Graphiti and GMF Compared

© 2011 by Koen Aers; made available under the EPL v1.0Graphiti and GMF Compared : Revisiting the Graph Editor47

Questions?