Customizing a GMF editor generated by EuGENia
So now you have created the first version of your GMF editor with EuGENia and it looks
almost like what you want - just a few tweaks and you are there. As EuGENia doesn't support all the features of GMF (otherwise it would be just as complex) you are finding that the tweaks you want to do are not supported by the annotations provided by EuGENia and therefore you need to go change one or more of the generated .gmfgraph, .gmfmap and .gmftool models manually. If you decide to do this, you won't be able to use EuGENia any more for your editor because it will overwrite your changes.
We've come across this situation many times and decided to do something about it. Since merging such complex models sensibly is virtually impossible, we've implemented support for user-defined transformations that complement the built-in transformations provided by EuGENia. Let's go straight to an example. We have the following
classdiagram metamodel:
@namespace(uri="classdiagram", prefix="classdiagram")
package classdiagram;
@gmf.diagram
class Model {
val Clazz[*] classes;
}
@gmf.node(label="name", figure="rectangle")
class Clazz {
attr String name;
@gmf.compartment(layout="list", collapsible="false")
val Attribute[*] attributes;
}
@gmf.node(label="name,type", figure="rectangle",
label.icon="false", label.pattern="{0}:{1}")
class Attribute {
attr String name;
attr String type;
}
and we follow the
standard EuGENia procedure to generate a GMF editor from it. The editor looks like this:
which is
almost what we want. What we
really want is something like this:
To get this, we need to customize the
classdiagram.gmfgraph model like this
so that we can get this:
To perform these changes automatically every time EuGENia is executed on
classdiagram.ecore, we can create a new EOL transformation called
ECore2GMF.eol and place it in the same folder with
classdiagram.ecore. EuGENia will then pick it up and execute it after the built-in transformation every time we invoke
Generate GMF tool, graph and map models action. In our case, the
ECore2GMF.eol customization transformation looks like this:
-- Find the compartment figure
var clazzAttributesCompartmentFigure = GmfGraph!Rectangle.all.
selectOne(r|r.name = 'ClazzAttributesCompartmentFigure');
-- ... and add a stack layout to it
clazzAttributesCompartmentFigure.layout = new GmfGraph!StackLayout;
-- Find the attribute figure
var attributeFigure = GmfGraph!Rectangle.all.
selectOne(r|r.name = 'AttributeFigure');
-- ... delete its border
delete attributeFigure.border;
-- ... set its outline to false
attributeFigure.outline = false;
-- ... and add a preferred size to it
var preferredSize = new GmfGraph!Dimension;
preferredSize.dx = 100;
preferredSize.dy = 16;
attributeFigure.preferredSize = preferredSize;
Similarly, if we needed to customize the logic behind the
Synchronize GMF Gen model action, we'd need to define a
FixGMFGen.eol transformation next to
classdiagram.ecore.
What models can I access from the ECore2GMF.eol and FixGMFGen.eol transformations?
In the
ECore2GMF.eol transformation you can access the Ecore metamodel (named
ECore), the tool model (named
GmfTool), the graph model (named
GmfGraph) and the map model (named
GmfMap).
In the
FixGMFGen.eol transformation you can access the ECore metamodel (named
ECore), and the generator model (named
GmfGen).
Getting assistance in writing these transformations
You'll most probably find
Exeed and the
EPackage Registry view to be useful for writing such transformations.