When creating a rich graphical editor the Model View Controller (MVC) design pattern makes life a lot easier. But it is often difficult to decide which libraries/frameworks to use. On the Eclipse platform GEF (Graphical Editing Framework) is a great solution but it can be challenging to figure out how to integrate with the parts you need. Since GEF is built on top of the Draw2d/SWT graphical libraries and is able to provide a powerful and consistent UI. However there are many considerations and pitfalls to take into account when getting started with GEF.
Some of my first large scale Java coding involved using and modifying GEF code. Luckily the GEF team provides many helpful examples showcasing the different features GEF offers. I will attempt to provide a concise introduction to the points that I found best helped me understand GEF.
MVC and GEF
The Model, View, Controller architecture may seem overly complex at first but it provides many benefits. It allows you to easily decouple the Model your program stores (Database, save files, memory structure, etc) from the view it displays to the user. This allows you to make your code more portable and easier to maintain and update.
GEF also creates an easy to use framework for managing the Controller, this is one of the more complicated concepts in MVC since it connects changes made in the model to corresponding figures in the view. GEF’s EditParts form the backbone of this framework. EditParts are supplemented by tools, palette, EditPolicies and commands, all of which help communicate actions from the keyboard and mouse to changes in the model and view.
One of the concepts that best helped me get an overview of how GEF implements the MVC architecture was one that explained the details of how a user’s actions result in changes to both the model and the view. There is a simple flow that begins whenever an action occurs. It traverses the MVC architecture via multiple different design patterns in the following order:
- The user acts on the view via the keyboard or mouse.
- GEF’s EditPartViewer determines what tool is being used and fires the appropriate request.
- The EditParts determine if they can create a corresponding command for that request
- The command is added to the command stack and executed, modifying the model
- The model fires the appropriate property change events after it has been modified
- EditParts update depending on what property changes are triggered. (For instance a new instance of a model element will trigger the EditPart Factory to instantiate a new corresponding EditPart)
- The EditParts update the view according to their new state.
- Luckily this whole process is handled by the GEF infrastructure. By creating/extending instances of the GraphicalEditorPartWithPalette, Commands, and EditPolicies you can create a the core of a GEF/MVC application.
Tips and some mistakes to avoid
I’ve found a few key concepts that are really helpful to keep in mind while developing with GEF:
Keep your EditParts out of your commands
In GEF Commands are created by EditParts/EditPolicies based on the Requests sent from user actions. They are responsible for updating the model. Ideally they should be simple atomic changes such as changing an elements size, location, color, or adding a child element. GEF provides CompoundCommands to allow you to combine these tasks into more complex commands. Just be careful to keep your EditParts out of your commands. Any logic requiring the EditPart (such as location of the request) should be handled within the getCommand() method in the EditPart and not within the command.
Don’t let your model get chatty with the view
The model should never directly modify the view. Any changes made on the model side should result in property changes being fired and then handled by the EditParts. They are then responsible for making changes to the figures.
Anything you want to save should be in the model
If there is some information you intend on saving it should be stored in the model. For instance if you intend on tracking where your data objects are in relation to eachother within the view, their coordinates will need to be saved in the model.
Balance the ratio of model -> controller -> view
You do not necessarily need exactly one EditPart for each model element or one figure for each EditPart. In fact this can lead to many problems. You want to make sure the hierarchy of the model view and controller all make sense within their own domains. After this you can decide how the mapping should work.
Other great GEF resources:
- GEF Description – http://wiki.eclipse.org/GEF_Description
- Eclipse GEF Project Page (Download) – http://www.eclipse.org/gef/gef_mvc/index.php
- GEF Tutorials – http://www.eclipse.org/gef/reference/articles.html
- Draw2d Tutorial – http://eclipse.org/articles/Article-GEF-Draw2d/GEF-Draw2d.html