For the public funded research projects IMES we are building graphical editors for functional nets and other systems. Since Graphiti is drawing a lot of interest, it is a good occasion for using the new technology. However, it turns out, that you have to write a lot of code. The Graphiti team seems to address this with a “Pattern Framework”, but it is hard to find documentation on this.
So what do you do to avoid writing boilerplate code? Of course, MDD with textual DSLs and M2T (i.e. code generation).
So the first draft of a language to specify editors was quickly implemented. Here are some core features as seen above:
- The DSL references the Ecore of the domain model, giving full content assist. This is used to e.g. generate the CreateFeature in Graphiti
- The “label” references an attribute in the ecore. This attribute is displayed as a label in the diagram. Moreover, the DirectEditingFeature and the Update Feature for the attribute is generated.
- In this example, a logical function can be at the root of the model, but it could also be a child of another logical function. So we have two contexts here. When the shape is created on / dragged to the diagram, the domain object is added to the functionNetworkProject.logicalFunction collection. On the other hand, if its container is another logical function, then the collection used is LogicalFunction.subFunction.
This generates code for the Create and Add Feature. In addition, it also creates a move feature, that rewires the containment if the shape is dragged from one container to another. The default behavior of Graphiti is two disallow moving an object out of its container.
With LogicalPorts, there is only the LogicalFunction context, so they cannot be placed on the diagram background, only within logical functions.
- Ports are usually placed on the border of the parent shape. In Graphiti, this requires a “MoveFeature”, that checks if the new position is valid. The “OnBorder” keyword creates such a feature that allows moving the ports on the border shape only.
- In the meta-model, a connection (Logical Channel) between to ports is not a reference, but a model element with references to the endpoints. The ObjectMapping specifies which element to create and which references to set for the endpoints.
- The channel is owned by the function that owns the functions connected by the channel (so this is two levels up). To allow for complex operations, the AddToModelFunc generates a stub that delegates the adding of the domain object to the model to a method that can be implemented manually.
- And finally, the connection has to know which elements / shapes it can connect.
And here is a screenshot of the generated editor:
The DSL/Generator are in an early phase and not designed to cover all use cases. But they will definitely reduce our implementation efforts for editors.
There is also another initiative to create a DSL for Graphiti editors, called “Spray”. However, no code has been published yet under “Spray” and since we could not wait for initial contributions, we just had to start anyway…