Wednesday, January 18, 2012

Impressions on GEF

For the Generic Graphical View project I've been digging deep into the Graphical Editing Framework (GEF) lately. GEF is the base technology below almost any graphical framework in the Eclipse environment. I wanted to keep the tool stack as low as possible and have the maximum control on everything so I decided to use GEF directly. Here are my impressions.

I really like GEF's base architecture: The separation between Draw2D and GEF, the concepts of Tools, Requests, EditParts and EditPolicies. It helps you to find the component to change in order to implement a new feature quickly. The pictures in the GEF online help really help
understanding this.


Pecularities

In some areas GEF appears to be kind of rusty. A whole bunch of relevant commercial products has been relying on it for years. Long term backward API compatibility has taken its toll. Some things definitely need a serious overhaul and often a better naming. I am very happy to hear that a 3.0 version is planned. Here is my wishlist for improvements:
  • Make coordinates double by default. Integer coordinates often result in rendering glitches due to rounding errors and are not well suited for scaling.
  • Add alpha channel (transparency) support.
  • Revise scaling of fonts: Sometimes a label's bounds don't match its text's extend.
  • Rename methods of the update mechanism. I am often confused about the semantics validate(), invalidate(), invalidateTree() or revalidate().
  • Rectangular bounds are not well suited for round things like ellipses. Similar to that, clipping child figures only makes sense for Viewports but nothing else. The need of an invisible container figure for side affixed children is really an ugly workaround.
  • Diagram layout does not take connection labels into account.
  • Add support for curve connections.
  • The feedback figures - the surrogates when a figure is moved or resized - seem to come from a time where hardware graphics acceleration was pure luxury. If you have nested edit parts you might have to reimplement the nested figure construction twice for nicer feedback.
  • Using a bit less inheritance and more composition would be fine.


Mutable Geometric Primitives

As many other graphics frameworks, GEF code tries to create as little new objects as possible. Geometrical primitives such as points, dimensions and rectangles are therefore mutable and reused often. There are even things as a static Rectangle.SINGLETON for temporary calculation. This pretty much reminds me of good old C++. I am not sure whether such optimization is still necessary. It results in pretty unreadable code:
Point p = figure.getLocation(); 
// p is the location in local coordinates
p.getParent().transformToParent(p);
// now p is in parent coordinates
Point q = p.add(p).scale(2):
// this will also modify p
You see: As the semantics of the variable changes, it is no surprise you cannot find a more expressive name than p. In addition, you have to be very careful if you are dealing with a reference or a copy. Modifying a Translatable (once again bad name, as Dimension also implements this interface) directly can also circumvent an event mechanism. This is really error prone. I'd strongly advise to introduce immutable primitives.


Coordinate Transformations

The way transformation between local, global and parent coordinates are handled is somehow unsuggestive. I've used various 2D and 3D scenegraph-based frameworks but I never got as confused with coordinates as in GEF. For example, if you have a ScalableLayeredPane showing some scaled content, its translateToAbsolute(Point) method will not take the scaling into account while translateToParent(Point) will.


Some Hints

Starting with GEF from zero is hard. You will likely spend a serious amount of time debugging why your diagram doesn't show anything at all. Better copy some basic setup from one of the GEF examples. Here are my favorite pitfalls:
  • missing minimum size on figure - figure does not show up at all in some layouts
  • wrong coordinate system - figures don't appear where they should, somtimes in nirvana
  • wrong layout manager, e.g. a plain XYLayout on a FreeformFigure - results in endless layout loop
  • reusing a geometry element instead of making a copy - completely unpredictable editor behavior
  • the default ChangeBoundsRequest does not take local coordinate systems into account
For better diagram layout algorithms the KIELER project offers a good choice.

11 comments:

Steven Kelly said...

I know GMF etc. have their problems, but I think you're jumping in the wrong direction. Back in 2004, it was already well established that using GEF to build a new graphical language and its modeling tool support is literally hundreds or even thousands of times slower than using MetaEdit+. The GEF Logic example is 10,000 lines of code (332KB, 120 files) in Eclipse, and yet took just 1 hour to implement in MetaEdit+.

Here are some links from my blog article back then:

"Experience reports in Dr. Dobb's, the OOPSLA workshop on Best Practices for Model-Driven Software Development, and the OOP conference have all found using Eclipse to build DSM tools to require a truly massive amount of effort: consistently between 1000 and 2000 times the effort needed with MetaEdit+. At the OOPSLA workshop where I presented, Anna Gerber, the author of the IBM Redbook on EMF and GEF, challenged my figures: she claimed Eclipse [GEF] is 'only' 600 times slower than MetaEdit+. I can live with that!"

Funnily enough, we just updated that old GEF Logic example for the new MetaEdit+ 5.0 beta, using dynamic ports. You can see it in the YouTube video Advanced Dynamic Symbols and Ports in MetaEdit+ or grab the MetaEdit+ 5.0 beta and its Eclipse IDE integration for yourself.

Jens v.P. said...

I'm sometimes surprised to learn that people do not know that GMF actually relies on GEF. Sometimes when people complain about GMF, and I ask them why they don't directly use GEF, they ask me what GEF is...

Actually, in GEF3D I tried to overcome some of the problems you mentioned:
- float coordinates are used instead of integer
- transparency is fully supported
- the geometry library of GEF3D distinguishes between mutable and immutable objects. For temporary items, GEF3D provides a cache in order to reuse these items.

My personal wish list for a new GEF would include:
- parameterized collections
- create figures with a factory (instead of hardwiring that in the edit part, which IMHO is a major design bug)

Unknown said...

@Steven:
I would not doubt that MetaEdit+ is great when it comes to building graphical model editors from scratch. But the views I am after are meant to complement existing Eclipse based editors, e.g. Xtext-based, make them work with any given repository technology (pure EMF, Xtext with workspace index etc.) The users should be able to go on using all of their IDE infrastructure and have some added value from the visualisation. So native Eclipse integration is a primary goal for me.

If you're comparing times to build the tool, you should also compare the times a user needs to create their models. Having to learn a new graphical tool will surely take them a while. I don't know MetaEdit+ in such detail that I could estimate the effort it would take to actually extend the editing behavior, e.g. add multitouch gesture support or a new way of creating nodes. This will also pay off in the user's time. A purely programmtic approach, e.g. using and extending GEF, feels a lot more promising to me.

Last but not least, MetaEdit+ is a commercial product. In my Generic Graph View I am experimenting with free, purely Eclipse based tools. So it feels a bit like you're comparing apples with oranges for the sake of advertising the latter :-)

Steven Kelly said...

@Jan: sure, you know the full context of your project, which should always decide what the right approach is.

I agree the comparison is apples and oranges - if one takes 1 hour and the other about a man-year, that's a massive difference. But at the end of the day your need is not for an apple or an orange, but to satisfy your hunger. I know you prefer the Eclipse / Java 'orange', but if getting one takes a year and getting a MetaEdit+ 'apple' takes an hour, you probably should consider at least trying the apple.

The effort to add multi-touch to MetaEdit+ would be the same as to add it to GEF. It's not dependent on the modeling language. Neither GEF nor MetaEdit+ offer it. The difference is that for GEF, you had to build it yourself, whereas in MetaEdit+ MetaCase would build it, not their customers.

I agree that the modeling time is generally the most important thing, but the major factor in that is the modeling language, not something like multitouch. The language can save you hours per day, multitouch a few minutes at best.

For some reason, I've yet to see a good graphical modeling language built in Eclipse. They tend to be copies of parts of UML: rather than raising the level of abstraction and using problem domain concepts, they want to be on a lower, technical level. I think the rationale is often "so users can do anything they want", which is also reflected in your reference to multitouch. Or then it's "so users aren't trapped in poor decisions made by the creator", which is reflected in your decision to move from GMF to GEF. And the final reason for not using something higher level is "so the users can get it for free", which again is something you mention.

That seems to be the Eclipse spirit, and I can see the attraction. I just don't believe it always leads to the most productive results. By the time something that should take an hour is actually taking a year, it's not really cheaper anymore is it?

GMF was built on GEF in the Eclipse spirit: allowing low level control, not constraining the user, and for free. You don't like the results. What makes you think that building a new 'GMF' in the same spirit will give different results this time?

As you've dropped down from GMF to GEF, what happens? You're already finding faults in GEF, so next you're going to be building a new GEF instead, working right on top of Draw2D. Presumably the next step after that is obvious too. You're a top Eclipse expert, so you can do that. But if Newton had used Eclipse, would he have proudly said "I can build so far, because I dig under the feet of giants"?

Andreas Graf said...

@Steven

I don't think Jan is going in the wrong direction. He's providing something for free with tight Eclipse integration where as your alternative seems less integrate and seems to cost around 5500 EUR for each end user according to your website.

These are two totally different goals and business models.

Unknown said...

@Steve:
I am not sure whether this is really a the right place to lead such a discussion, as I disagree in so many points :-). But let me pick one:

The customers I have met had very strong and very different opinions when it comes to the behavior of a graphical editor. Believe it or not a double instead of a single click to accomplish a specific task can really be a blocker. Multitouch was just another example of mine, but a serious one: It is the way people use a modern trackpad, where a conventional drag gesture is really inconvenient. I agree, the DSL matters most, but you have to adapt to different usability requirements if you want to keep your customers. What should they think when you say multitouch does not matter? This is why I'd always go for the OS framework/programming solution instead of relying on a product when it comes to graphical UI.

Most of our customers are very satisfied with DSLs based on Xtext. I am just figuring out a simple way for adding read-only graphical overviews. In fact, I went *up* from Draw2d to GEF to make these conventiently configurable. I am not going to rebuild GMF. I just wonder why we are building layers and layers on top of GEF in order to make it usable instead of trying to figure out how to rebuild GEF as extensible and open as e.g. Xtext is.

Steven Kelly said...

@Phillipus: sorry, I know this conversation must be frustrating to someone already committed to GEF coding.

@Andreas: exactly: If you save a year's work, how does that weigh against the number of licenses you'd have to buy. That's the basis for a rational decision.

Let's say you start with the tiny Logic example and build it for a year, then work for 4 more years improving it as people use it. If your time costs 70k to the company, that makes MetaEdit+ the cheaper choice for anything up to 60 licenses. With a real, bigger language, the number would be much higher.

As you say, there is plenty of room for different business models. With Domain-Specific Modeling, the number of people using a given language is naturally limited: by only having to address a narrower domain, you can make it much more productive. There aren't many DSM cases with over 100 users, and MetaCase has been here for 20 years, so I guess there's a market there :).

@Jan: Sure, all tools have to offer UI customization options, whether as settings, consulting work, or done for free to close a deal (and probably turned into a setting).

Unlike you, I wouldn't "always go for" the same choice between open source library vs. commercial product. We build MetaEdit+ with a mixture, and we release some things we build commercially and others as free open source.

Where we both can agree is that it's great that you're adding some graphical support to Xtext. The "graphical vs. text" argument is as big a misdirection as "free open source vs. commercial product": both have their uses. Good luck with the work, and keep us posted - it will be fascinating to see how people react, whether read-only is enough, etc.

PS Funny to think that MetaEdit has actually had read-only support for textual syntax since 1995, through its generators, and I never realised it before!

Andreas Graf said...

@Steven
I completely agree. For the Eclipse community, I would always recommend to compare costs of DIY or using a tool like Obeo Designer. Spray might come up as an alternative as well.

Unknown said...

I did not censor Steven, so I am neither censoring Philipus. But I am cutting the discussion here. We have really run off topic and have yet started to get personal.

GEF is going to have a new major release. My primary intent with this blog entry was to deliver my experiences and encourage others to do so, too, such that the GEF committers have some feedback for their new attempt. Unfortunately, this worked only for the first comments. Now, I guess we have trolled away everybody with valuable input to that initial topic. It's a pity.

It's my fault: I am easily involved into discussions, and I failed to block the MetaEdit+, business model, graphical vs textual, Eclipse vs. MetaCase topics early.

All of you have their points, but you should really consider if you're doing yourself and your companies a favor by the way you're using this comment thread.

Jan Krákora said...

Hi Jan, nice blog.

I'm developing a GEF editor right now and I'm very interested in the KIELER layout algorithm you've mentioned.

How did use it?? Because from theirs wiki I can see its only applicable to GMF, not to pure GEF.

Unknown said...

Not sure about this. Maybe ask the KIELER developers, e.g. on their developers list? For my project, I have built my own integration layer, as I was comparing several layout frameworks and needed a common interface.