Show last authors
1 This tutorial will introduce another kind of concrete syntax for your models, namely a graphical syntax. Instead of writing models in a textual format, they are created by dragging elements from a palette into a two-dimensional plane. The framework we will employ here is [[Graphiti>>url:http://www.eclipse.org/graphiti/||shape="rect"]], which is based on the [[Graphical Editing Framework>>url:http://www.eclipse.org/gef/||shape="rect"]].
2
3 === Contents ===
4
5
6
7 {{toc maxLevel="2"/}}
8
9 = Defining a Diagram Type =
10
11 The main documentation of Graphiti is found in the [[Eclipse online help>>url:http://help.eclipse.org/juno/nav/23||shape="rect"]], which is also found in the Eclipse application (//Help// → //Help Contents//). If you don't have Graphiti yet, install it from the Juno release update site, //Modeling// category. The first step of this tutorial consists of defining a diagram type for Turing Machines and adding a wizard dialog for the creation of new diagrams.
12
13 1. Read the [[Graphiti Introduction>>url:http://help.eclipse.org/juno/topic/org.eclipse.graphiti.doc/resources/docu/gfw/graphiti-introduction.htm?cp=23_0_0||shape="rect"]].
14 1. Create a new plugin named de.cau.cs.rtprak.login.turing.graphiti (like in previous tutorials, replace "login" by your login name) and add dependencies to the following plugins:\\
15 1*. org.eclipse.core.runtime
16 1*. org.eclipse.core resources
17 1*. org.eclipse.ui
18 1*. org.eclipse.ui.ide
19 1*. org.eclipse.emf.ecore.xmi
20 1*. org.eclipse.emf.transaction
21 1*. org.eclipse.emf.workspace
22 1*. org.eclipse.graphiti
23 1*. org.eclipse.graphiti.ui
24 1*. de.cau.cs.rtprak.login.turingmodel
25 1. Create a class {{code language="none"}}TuringDiagramTypeProvider{{/code}} with superclass {{code language="none"}}org.eclipse.graphiti.dt.AbstractDiagramTypeProvider{{/code}}.
26 1. Open plugin.xml and create an extension for org.eclipse.graphiti.ui.diagramTypes with a //diagramType// element:\\
27 1*. //id: //de.cau.cs.rtprak.TuringDiagramType
28 1*. //type: //turing
29 1*. //name: //Turing Diagram Type
30 1. Create an extension for org.eclipse.graphiti.ui.diagramTypeProviders with a //diagramTypeProvider// element:\\
31 1*. //id~:// de.cau.cs.rtprak.login.TuringDiagramTypeProvider
32 1*. //name~:// Turing Diagram
33 1*. //class~:// name of the {{code language="none"}}TuringDiagramTypeProvider{{/code}} class
34 1. Add a //diagramType// element to the //diagramTypeProvider// with id de.cau.cs.rtprak.TuringDiagramType.
35 1. Create a class {{code language="none"}}TuringFeatureProvider{{/code}} with superclass {{code language="none"}}org.eclipse.graphiti.ui.features.DefaultFeatureProvider{{/code}}.
36 1. (((
37 Add the following constructor to {{code language="none"}}TuringDiagramTypeProvider{{/code}}:
38
39 {{code theme="Eclipse" language="java"}}
40 /**
41 * Create a Turing diagram type provider.
42 */
43 public TuringDiagramTypeProvider() {
44 setFeatureProvider(new TuringFeatureProvider(this));
45 }
46 {{/code}}
47 )))
48 1. Copy [[attach:GraphitiNewWizard.java]] and [[attach:CreationWizardPage.java]] to your plugin, adapting the package name accordingly. These files implement a generic wizard dialog for creating Graphiti-based models.
49 1. Create a subclass of {{code language="none"}}GraphitiNewWizard{{/code}} for specifying a concrete wizard dialog for your models.\\
50 1*. (((
51 Add a constructor that calls a super-constructor with according parameters for configuration:
52
53 {{code theme="Eclipse" language="java"}}
54 super("Turing Machine", "tudi", "turing", "turing",
55 org.eclipse.graphiti.ui.editor.DiagramEditor.DIAGRAM_EDITOR_ID);
56 {{/code}}
57
58 Diagrams are stored in two separate files, one containing the actual Turing Machine model and one containing the specific graphical elements used to represent the model. Here it is assumed that {{code language="none"}}"turing"{{/code}} is the file extension for Turing Machine models (this depends on how you configured your EMF model), while {{code language="none"}}"tudi"{{/code}} will be the file extension for diagrams. //Hint~:// by selecting {{code language="none"}}"tuxt"{{/code}} as domain model file extension your models will be stored in the textual format instead of XMI. However, this requires the created models to always be in a serializable state.
59 )))
60 1*. Implement the {{code language="none"}}createModel{{/code}} method by creating and returning an instance of the top-level element of your Turing Machines, e.g. {{code language="none"}}TuringMachine{{/code}}.
61 1*. Register the new wizard class in your plugin.xml using a //wizard// extension for org.eclipse.ui.newWizards (you only need to choose an id and name and set the correct class name).
62 1. Include the new plugin in your Eclipse run configuration and start it. Create a Turing Machine diagram with your new wizard: //File//→ //New//→ //Other...//→ //Other//→ //Turing Machine//. This opens a Graphiti diagram editor for the new file, but you cannot do anything in that editor, since the palette is still empty.
63 1. In order to open a previously created {{code language="none"}}tudi{{/code}} file, right-click it → //Open With//→ //Other...//→ //Graphiti Diagram Editor//. This setting for {{code language="none"}}tudi{{/code}} files will be saved in your workspace preferences.
64
65 = Creating and Adding Elements =
66
67 The next step is to write so-called //features// for creating and adding elements to the diagrams. Each type of graphical element requires a //create// feature for the creation of corresponding meta model (//business model//) elements, and an //add// feature for adding a specific graphical representation to the diagram. A graphical representation is modeled with a so-called //pictogram element//, which contains a structure of //graphics algorithms// that specify how the element is rendered.
68
69 1. (((
70 Add the following feature class to your plugin, adapting references to meta model elements to your Turing Machine definition:
71
72 {{code theme="Eclipse" language="java"}}
73 import java.util.List;
74 import org.eclipse.emf.ecore.EObject;
75 import org.eclipse.graphiti.features.IFeatureProvider;
76 import org.eclipse.graphiti.features.context.ICreateContext;
77 import org.eclipse.graphiti.features.impl.AbstractCreateFeature;
78 import org.eclipse.graphiti.mm.pictograms.Diagram;
79
80 import de.cau.cs.rtprak.login.turingmodel.State;
81 import de.cau.cs.rtprak.login.turingmodel.TuringFactory;
82 import de.cau.cs.rtprak.login.turingmodel.TuringMachine;
83
84 /**
85 * A create feature for Turing Machine states.
86 *
87 * @author msp
88 */
89 public class StateCreateFeature extends AbstractCreateFeature {
90
91 /**
92 * Constructor for a state create feature.
93 *
94 * @param fp the feature provider for which the feature is created
95 */
96 public StateCreateFeature(IFeatureProvider fp) {
97 super(fp, "State", "Create a State");
98 }
99
100 /**
101 * {@inheritDoc}
102 */
103 public boolean canCreate(ICreateContext context) {
104 return context.getTargetContainer() instanceof Diagram;
105 }
106
107 /**
108 * {@inheritDoc}
109 */
110 public Object[] create(ICreateContext context) {
111 // get the container business element
112 List<EObject> containerObjects = context.getTargetContainer().getLink().getBusinessObjects();
113 if (containerObjects.isEmpty() || !(containerObjects.get(0) instanceof TuringMachine)) {
114 throw new IllegalStateException("The diagram does not contain a Turing Machine.");
115 }
116 TuringMachine machine = (TuringMachine) containerObjects.get(0);
117
118 // create a new state
119 State state = TuringFactory.eINSTANCE.createState();
120 machine.getStates().add(state);
121
122 // add the corresponding graphical representation
123 addGraphicalRepresentation(context, state);
124
125 return new Object[] { state };
126 }
127
128 }
129 {{/code}}
130 )))
131 1. (((
132 Add the following method to TuringFeatureProvider{{code language="none"}}{{/code}}, defining the content of the diagram editor's palette:
133
134 {{code theme="Eclipse" language="java"}}
135 /**
136 * {@inheritDoc}
137 */
138 @Override
139 public ICreateFeature[] getCreateFeatures() {
140 return new ICreateFeature[] { new StateCreateFeature(this) };
141 }
142 {{/code}}
143 )))
144 1. (((
145 Add the following feature class to your plugin and implement the {{code language="none"}}add{{/code}} method:
146
147 {{code theme="Eclipse" language="java"}}
148 import org.eclipse.graphiti.features.IFeatureProvider;
149 import org.eclipse.graphiti.features.context.IAddContext;
150 import org.eclipse.graphiti.features.impl.AbstractAddShapeFeature;
151 import org.eclipse.graphiti.mm.pictograms.ContainerShape;
152 import org.eclipse.graphiti.mm.pictograms.Diagram;
153 import org.eclipse.graphiti.mm.pictograms.PictogramElement;
154 import org.eclipse.graphiti.services.Graphiti;
155 import org.eclipse.graphiti.services.IGaService;
156
157 import de.cau.cs.rtprak.login.turingmodel.State;
158
159 /**
160 * An add feature for Turing Machine states.
161 *
162 * @author msp
163 */
164 public class StateAddFeature extends AbstractAddShapeFeature {
165
166 /**
167 * Constructor for a state add feature.
168 *
169 * @param fp the feature provider for which the feature is created
170 */
171 public StateAddFeature(IFeatureProvider fp) {
172 super(fp);
173 }
174
175 /**
176 * {@inheritDoc}
177 */
178 public boolean canAdd(IAddContext context) {
179 return context.getNewObject() instanceof State
180 && context.getTargetContainer() instanceof Diagram;
181 }
182
183 /**
184 * {@inheritDoc}
185 */
186 public PictogramElement add(IAddContext context) {
187 // create a pictogram element for the state
188 ContainerShape containerShape = Graphiti.getPeCreateService().createContainerShape(
189 context.getTargetContainer(), true);
190  
191 // TODO specify the concrete representation by adding at least one graphics algorithm
192
193 link(containerShape, context.getNewObject());
194 return containerShape;
195 }
196
197 }
198 {{/code}}
199
200 Use {{code language="none"}}Graphiti.getGaService(){{/code}} to get a service class for creating graphics algorithms and modifying their properties. You are free to design your model elements as you like. Find more information on how to solve this task in the official [[Graphiti Tutorial>>url:http://help.eclipse.org/juno/nav/23_1||shape="rect"]].
201 )))
202 1. (((
203 Add the following method to TuringFeatureProvider{{code language="none"}}{{/code}}:
204
205 {{code theme="Eclipse" language="java"}}
206 private IAddFeature stateAddFeature = new StateAddFeature(this);
207
208 /**
209 * {@inheritDoc}
210 */
211 @Override
212 public IAddFeature getAddFeature(IAddContext context) {
213 if (stateAddFeature.canAdd(context)) {
214 return stateAddFeature;
215 }
216 return super.getAddFeature(context);
217 }
218 {{/code}}
219 )))
220 1. Test the features in the diagram editor. You should now be able to select "State" in the editor's palette. Use this to create a few states. Note that if you create a state and later change the graphical representation in StateAddFeature, the previously created state will still look the same, since the add feature code is only applied to new states created from the palette.