Enabling Dynamic Templates in GMF
Also known as Aspect Oriented Programming, GMF allows you to specify a location for custom dynamic templates, which are compiled and added to your plugin when the .gmfgen is being used to generate the diagram code.
This is based on two references: A really good presentation (see page 17), and a news posting. This example is based on GMF 2.0.1, but it should work fine with GMF 2.2 as well.
In this example, we want to change our getDestroyElementCommand() in my.diagram.edit.policies.PageItemSemanticEditPolicy:
/**
* @generated
*/
protected Command getDestroyElementCommand(DestroyElementRequest req) {
CompoundCommand cc = getDestroyEdgesCommand();
addDestroyShortcutsCommand(cc);
cc.add(getGEFWrapper(new DestroyElementCommand(req)));
return cc.unwrap();
}
To:
/**
* @generated
*/
protected Command getDestroyElementCommand(DestroyElementRequest req) {
CompoundCommand cc = getDestroyEdgesCommand();
addDestroyShortcutsCommand(cc);
cc.add(getGEFWrapper(new DestroyElementCommand(req)));
System.out.println("hello, world!");
return cc.unwrap();
}
- Get the GMF Codegen source (includes the actual templates used to generate your plugin) and extract it somewhere.
- Search through the templates for getDestroyElementCommand
- Hunt around until you find a template that looks useful: in my case, I found xpt/diagram/editpolicies/NodeItemSemanticEditPolicy.xpt.
- Look in this template to find the DEFINE that make up this command: in my case, I decided to modify destroySemanticElement which was part of the code used to create getDestroyElementCommand:
«DEFINE destroySemanticElement FOR gmfgen::GenNode-»
«EXPAND fixElementToDeleteIfShortcut-»
cc.add(getGEFWrapper(new org.eclipse.gmf.runtime.emf.type.core.commands.DestroyElementCommand(req)));
«ENDDEFINE»
- Create a new .xpt file like so (note: the IMPORT statement is for GMF 2.2):
«IMPORT 'http://www.eclipse.org/gmf/2009/GenModel'»
«EXTENSION xpt::diagram::Utils»
«EXTENSION xpt::GenModelUtils»
«AROUND destroySemanticElement FOR gmfgen::GenNode-»
«targetDef.proceed()»
System.out.println("hello, world!");
«ENDAROUND»
- You will notice above: AROUND is used to specify that we don’t want to replace the original element, we want to modify it.
- Also, «targetDef.proceed()» is the terminology to include the original template code (so we don’t lose functionality).
- Save this file into templates/aspects/xpt/diagram/editpolicies/NodeItemSemanticEditPolicy.xpt. This is a copy of the original template location, but notice the aspects part of the directory!
- Go into your .gmfgen
- Change Gen Editor Generator > Dynamic Templates to true
- Change Gen Editor Generator > Template Directory to /my.model/templates/
- You can now generate modified templates!
I did all of this in my own project, which you can view the diff on Google Code to see what I did