|
Re: How to generate a description for a node? [message #808476 is a reply to message #808398] |
Mon, 27 February 2012 20:40 |
Michael Golubev Messages: 383 Registered: July 2009 |
Senior Member |
|
|
Hello,
You may just add the call like setToolTip(new Label("<description>")) into the constructor of every figure inner class.
If you are curious, there is a better (generative) way to achieve the same via templates & input model artifacts, but as it will require A BIT more work , I would not recommend it if your model has less than 5 different nodes.
Regards,
Michael "Borlander" Golubev
at Montages Think Tank, Prague, Czech Republic
Montages AG, Zürich, Switzerland
|
|
|
|
|
Re: How to generate a description for a node? [message #809082 is a reply to message #808673] |
Tue, 28 February 2012 13:11 |
Michael Golubev Messages: 383 Registered: July 2009 |
Senior Member |
|
|
Hello,
Below I will show step-by-step implementation of the similar requirements for the TaiPan sample. [update] It is an application of the Aurelien's idea for your particular use case
Sorry for too many details below, I just feel that the whole idea of AROUND'ing is kinda undervalued by the community, so I will try to explain how I think while solving the problems like this. If you don't interested in details, just do the steps 3) and 4) and copy Descriptions.qvto and NodeEditPart.xpt from attached archive into the new folder created at 4).
So, I made the following:
1) I identified the place in the generated code where I want custom changes. Based on my previous idea about tooltip I decided that the XXXEditPart#createNodeFigure() method is a good place. By default GMFT generates something like:
protected NodeFigure createNodeFigure() {
NodeFigure figure = createNodePlate();
figure.setLayoutManager(new StackLayout());
IFigure shape = createNodeShape();
figure.add(shape);
contentPane = setupContentPane(shape);
return figure;
}
and I would like to change it to something like:
protected NodeFigure createNodeFigure() {
NodeFigure figure = createNodePlate();
figure.setLayoutManager(new StackLayout());
IFigure shape = createNodeShape();
//CODE FROM AROUND
shape.setToolTip(new Label("Description for Ship (from TaiPan sample)"));
figure.add(shape);
contentPane = setupContentPane(shape);
return figure;
}
2. I have found the template that generates the createNodeFigure method. It was tricky because just a text search through *.xpt files for "createNodeFigure" does not help (normally it should). Fortunately, the generated method has a long generated comment and searching for 'Body of this method does not depend on settings in generation model' from the comment text has found the following snippet in the
\org.eclipse.gmf.codegen\templates\impl\diagram\editparts\NodeEditPart.xpt:
«DEFINE createFigure FOR gmfgen::GenNode-»
«EXPAND xpt::Common::generatedMemberComment(
'Creates figure for this edit part.\n' +
'\n' +
'Body of this method does not depend on settings in generation model\n' +
'so you may safely remove <i>generated</i> tag and modify it.\n'
)»
protected org.eclipse.gmf.runtime.gef.ui.figures.NodeFigure create«IF hasBorderItems(self)»Main«ELSE»Node«ENDIF»Figure() {
org.eclipse.gmf.runtime.gef.ui.figures.NodeFigure figure = createNodePlate();
figure.setLayoutManager(new org.eclipse.draw2d.StackLayout());
org.eclipse.draw2d.IFigure shape = createNodeShape();
figure.add(shape);
contentPane = setupContentPane(shape);
return figure;
}
«ENDDEFINE»
3. In order to enable custom templates we will go to the taipan.gmfgen and in the property sheet for GenEditorGenerator will set:
GenEditorGenerator#dynamicTemplates = true
GenEditorGenerator#templateDirectory = /org.eclipse.gmf.examples.taipan/templates/
(obviuosly you need to change the project name)
4. Now we will create the folder structure for custom templates. We start from creating the path specified in the GenEditorGenerator#templateDirectory (/org.eclipse.gmf.examples.taipan/templates/). Inside we will create the magic folder "/aspects" and inside we will mimic the folder structure for the template we want to override. It gives the whole path of "/org.eclipse.gmf.examples.taipan/templates/aspects/impl/diagram/editparts/".
5. Here we will create the file that will store a logic about the per-class descriptions. I created /org.eclipse.gmf.examples.taipan/templates/aspects/impl/diagram/editparts/Descriptions.qvto as follows:
modeltype gmfgen uses "http://www.eclipse.org/gmf/2009/GenModel";
modeltype ecore uses "http://www.eclipse.org/emf/2002/Ecore";
library Descriptions;
helper getDescriptionForToolTip(node : gmfgen::GenNode) : String {
return
let eClass : ecore::EClass = node.modelFacet.metaClass.ecoreClass in
if eClass.oclIsUndefined() then null
else if eClass.name = 'MyEClass1' then 'Description for MyEClass1'
else if eClass.name = 'MyEClass2' then 'Description for MyEClass2'
else if eClass.name = 'MyEClass3' then 'Description for MyEClass3'
else if eClass.name = 'Ship' then 'Description for Ship (from TaiPan sample)'
endif endif endif endif endif;
}
This is the single place that has all related logic, which is a good thing
6. Now we will override the default template to use this implemented logic. In the same folder we will create a /org.eclipse.gmf.examples.taipan/templates/aspects/impl/diagram/editparts/NodeEditPart.xpt as follows:
«IMPORT 'http://www.eclipse.org/gmf/2009/GenModel'»
«EXTENSION xpt::diagram::ViewmapAttributesUtils»
«EXTENSION xpt::diagram::editparts::Utils»
«EXTENSION xpt::diagram::Utils»
«EXTENSION aspects::impl::diagram::editparts::Descriptions»
«AROUND createFigure FOR gmfgen::GenNode-»
«EXPAND xpt::Common::generatedMemberComment(
'Creates figure for this edit part.\n' +
'\n' +
'Body of this method does not depend on settings in generation model\n' +
'so you may safely remove <i>generated</i> tag and modify it.\n'
)»
protected org.eclipse.gmf.runtime.gef.ui.figures.NodeFigure create«IF hasBorderItems(self)»Main«ELSE»Node«ENDIF»Figure() {
org.eclipse.gmf.runtime.gef.ui.figures.NodeFigure figure = createNodePlate();
figure.setLayoutManager(new org.eclipse.draw2d.StackLayout());
org.eclipse.draw2d.IFigure shape = createNodeShape();
«LET getDescriptionForToolTip(self) AS description-»
«IF description <> null-»
//CODE FROM AROUND
shape.setToolTip(new org.eclipse.draw2d.Label("«description»"));
«ENDIF-»
«ENDLET-»
figure.add(shape);
contentPane = setupContentPane(shape);
return figure;
}
«ENDAROUND»
In fact, I
- started from copy-pasting the default NodeEditPart.xpt here,
- added the «EXTENSION aspects::impl::diagram::editparts::Descriptions» to import just created Descriptions.qvto helper (note that I have included 'aspects' into the fully qualified name of helper)
- then I deleted all the contents except the subject DEFINE, and replaced DEFINE -> AROUND (and ENDDEFINE -> ENDAROUND)
- finally I added the change I want to introduce:
«LET getDescriptionForToolTip(self) AS description-»
«IF description <> null-»
//CODE FROM AROUND
shape.setToolTip(new org.eclipse.draw2d.Label("«description»"));
«ENDIF-»
«ENDLET-»
Now we are done, regenerating the diagram creates the code we were willing to have in ShipEditPart:
protected NodeFigure createNodeFigure() {
NodeFigure figure = createNodePlate();
figure.setLayoutManager(new StackLayout());
IFigure shape = createNodeShape();
//CODE FROM AROUND
shape.setToolTip(new Label("Description for Ship (from TaiPan sample)"));
figure.add(shape);
contentPane = setupContentPane(shape);
return figure;
}
Note that this way
- we haven't introduced any generated @not code, so migration to the GMFT 3.0 will be easier
- we may be pretty sure that we will have the same tooltips for all Ship's (there may be many similar editpart classes)
- we have the single artifact (Descriptions.qvto) that knows the per-EClass descriptions, so it should be simpler to maintain
Just in case, I have attached dynamic-templates.zip containing the templates and files for the TaiPan sample mentioned above.
Regards,
Michael
[Updated on: Tue, 28 February 2012 13:12] Report message to a moderator
|
|
|
Powered by
FUDForum. Page generated in 0.03539 seconds