So the year 2016 has already been upon us for three weeks, and one of my resolutions is to write more blog-posts. Let’s see how this turns out…
For one of my customers, I am currently developing a GEF/Draw2D-based editor. I chose GEF 3.x instead of GEF4 for the implementation mainly for two reasons:
- The target platform of my client as of now is Eclipse Luna and I am unsure if I would have been able to get GEF4 to work on Luna (there are other EMF features in the target platform used by different components, so I am not very flexible with respect to versions in the EMF field)
- Due to its maturity, there seems to be more documentation out there for GEF 3.x than there is for GEF4. For example, I have found the Kindle version of The Eclipse Graphical Editing Framework on Amazon. While this book does not contain the answer to all obstacles I came over, it contains a lot of answers and explanations, and I can recommend it as a good reference and tutorial.
In the next few blog posts, I will point out some of these obstacles which I were not able to find a solution right away, and I hope that by writing about them, and how I solved them, I will help others to find answers to similar issues faster.
So here goes–something simple to start off:
Untyped EditPart members
Obstacle:
Well—not really an "obstacle", but I found it quite annoying that org.eclipse.gef.editparts.AbstractGraphicalEditPart
returns general types for getModel(), getFigure()
, and getParent()
.
I ended up with a lot of code like this:
MyFigure fig = (MyFigure)getFigure(); MyModel m = (MyModel)getModel(); MyParentEditPart p = (MyParentEditPart)getParent();
<do something with fig, m, and p>
Solution:
So, I refactored my code and wrote a custom base class for my EditParts, which uses type parameters to specify the concrete types for the model, figure, and parent edit part types. Then I have overridden t he getXxx()-methods with their covariant specializations.
public abstract class EditPartBase< F extends Figure, M extends Object, P extends AbstractGraphicalEditPart > extends AbstractGraphicalEditPart { ... }
This makes writing things like
((MyFigure)getFigure()).setModel((MyModel)getModel());
much more readable, because now I can write
getFigure().setModel(getModel());
and if you are using Xtend like me, you can even write
getFigure.model = model
Plus, this common base class is a good place for utility methods. For example, I need access to the ZoomManager in several edit parts, so I also added a getZoomManager()
method.
More on Zooming in one of the next posts…
Here is the final EditPartBase class:
/** * Abstract base class for EditParts which narrows the types so the code of derived classes is easier to read * @param <F> The figure type created by this edit part * @param <M> The model type managed by this edit part * @param <P> The concrete type of this edit part's parent */ public abstract class EditPartBase<F extends Figure, M extends Object, P extends AbstractGraphicalEditPart> extends AbstractGraphicalEditPart { @Override @SuppressWarnings("unchecked") public M getModel() { return (M) super.getModel(); } @Override @SuppressWarnings("unchecked") public F getFigure() { return (F) super.getFigure(); } @Override @SuppressWarnings("unchecked") public P getParent() { return (P) super.getParent(); } @Override protected abstract F createFigure(); /** * Retrieve the {@link ZoomManager} * @return the ZoomManager of this parts scalable root part */ public ZoomManager getZoomManager() { return ((ZoomManager) getViewer().getProperty(ZoomManager.class.toString())); } }
Until next time ... Happy Coding!