Graphiti is a great framework for creating graphical editors in Eclipse. With every framework, there a different ways on how to use them. And, as was written on the Graphiti forum, there is no “one best way”. At Eclipse demo camp Munich, I introduced the way we use Graphiti, which differs to some degree from the way shown in Graphiti tutorial.
First, let’s have a look at the general structure of a Graphiti application. To implement a diagram, the programmer needs to implement so-called “features” for all the diagram elements. Features take care of moving, resizing, creating diagram elements and they modify the domain model.
The diagram is stored in an EMF model, defined by Graphiti. The diagram meta-model is considered fixed by Graphiti.
- Lots of implementation of features: For each graphical element, a number of features has to be implemented. Graphiti has a new approach called pattern. However, we want some additional flexibility and features, so we created a DSL for the generation of features.
- Integration of diagram model, domain model and navigator: We leave all the logic on how to load models to Eclipse Sphinx workspace management. That gives us a nice integration with the model explorer out-of-the-box.
- Adding additional elements. We want to have floating labels for nodes, ports that stick to borders, fancier connection ends etc. So we need to add additional information to the graphical elements.
Since the diagram .ecore is fixed and the Graphiti philosophy is to build editors purely by API (as e.g. compared to GMF, whose generators are not exactly popular), Graphiti provides an API to set string based properties.But they do have some drawbacks:
Luckily, Graphiti, EMF and Eclipse are flexible enough to easily work with different approaches. Let’s have a look at what happens when working with a Graphiti editor: EMF loads a .diagram file and creates an in-memory representation of Graphiti’s Diagram classes. Both the Graphiti Editor Framework as well as our user implemented features work on these classes.
Now, we can easily define our own ecore (here called .duankou) that contains classes that extend the original Graphiti classes. We can add new methods and attributes. When opening an .duankou file will load the classes. Because of inheritance, Graphiti will see all of its familiar classes. However, in our features, we know that there is more and can cast to our extended classes.
Here is an example of the “SmartShape” that inherits from ContainerShape. It is just called SmartShape because of lack of creativity when naming. Works perfectly fine. Everything gets loaded and our new attributes are stored in the “new” diagram files. The only problem is: The Graphiti classes’ visibility is such that we get a lot of warnings that we are not allowed to extend them. We just ignore that warning.