Jump to: navigation, search

GMF Propsheet Customization

How-to customize property sheet for your gmf editor.

In org.eclipse.gmf.gmfgraph.editor we have customized the property sheet supplied by this editor by customizing gmf.genmodel templates to work with our joint propsheet.ecore metamodel. This actually provided a framework to customize your property sheets. So customizing templates together with providing a joint metamodel for the gmfgen is actually a good example of customizing gmf for making frameworks for it!

But now let’s walk through all the steps needed for using our resulted propsheet framework.

We assume that at the moment you have your specific metamodel, described in .ecore, and have already generated your DSL editor, provided by GMF. And now you want to customize the property sheet for your editor with our propsheet framework.

So how does it work?

We can generate most of the code needed, if you reuse customized templates from org.eclipse.gmf.gmfgraph.editor. More precisely, you need only PropertySection.xpt (along with Utils.ext). If you have a look inside, you will notice, that all the template code is set up to use PropSheet metamodel, and its custom code is target metamodel independent. You will also notice, that for all of the general functionality this class org.eclipse.gmf.graphdef.editor.sheet.AbstractCustomSectionParent (it is located in “src-extra” source folder of the project). You can have a glance at it to see the graphical services available. I have mentioned, that this template produces “most” of the code, so actually we still need some NOT generated parts in complicated cases of operating metamodel, so one of the 2 tabs used in our gmfgraph.editor contains such parts (see org.eclipse.gmf.graphdef.editor.sheet.GeneratedLayoutPropertySection).

The main feature of the template engine, which have made it possible to have a framework, is xpand automatic searching for referenced objects within the same resource set. In our graphical description of propsheet widgets we only reference gmf Custom Property Tabs, and gmfgen itself knows nothing of our extension.

Let’s give it a try.

Small tutorial. Part 1. Introduction.

For quick start we will first change already customized tabs of our main org.eclipse.gmf.graphdef.editor plugin. So the first thing you’ll need is checking out this module into your workspace from its CVS location in sdk-experimental.

The second important thing you have to do first, is Generating Model Code org.eclipse.gmf.graphdef.propsheet and Generating Edit Code org.eclipse.gmf.graphdef.propsheet.edit plugins from the propsheet.genmodel, that should exist in the models folder of graphdef.editor plugin. After these projects are generated, you can Export them as Deployable plug-ins and fragments into your current platform (or import these in development workbench, if you are currently using target one for work with).

Finally, as one of the most simple, but useful examples, let’s provide users with a way to specify names for figures at last. This functionality was lost when we have switched to customized properties presentation. Since there could be many reasons for Which custom tab should we choose to meaningfully add this text field, let’s simply make a new one. As usual, open the gmf generation model from models/graphdef.gmfgen, and add one more Custom Property Tab child for Property Sheet node (these nodes are part of the common gmfgen description, so you can find them under Gen Editor Generator customization root, as always).

NewCustomPropertyTab.png

I have given it “genLabel” id and chosen “Name” for its label. I have also changed the implementation class name a little (just to make it prettier), and now it is going to be “GeneratedNamePropertySection”.

Now we need to decide, which objects does it make sense to set name for – and this actually means tiding our property with the metamodel, specifying the blackbox from which the value should be initially taken, and where it should be saved afterwards. Actually, with the normal development flow, you always think of this first, because the metamodel already exists and its properties are already known, and now you are just thinking of how to show them in widgets. So, looking to our domain gmfgraph.ecore metamodel we can notice, that every org.eclipse.gmf.gmfgraph.Identity object can have a name in metamodel, so that tells us of what filter should we add to show our tab: we want the tab to be shown for Identities. OK, let’s add New Child to our Custom Property Tab named Name of type Custom filter, and make it point to the org.eclipse.jface.viewers.IFilter class which would check selection’s type. There are filters for other custom tabs already implemented within org.eclipse.gmf.graphdef.editor.part.PropertySectionFilters (being the custom implementation class, it could be found in src-extra folder as well), and so all we need is making some new static nested class with similar code. Coping ShapeFilter and replacing Shape with Identity works fine for me, so let’s do it.


public static class IdentityFilter implements IFilter {
	public boolean select(Object toTest) {
		Object transformed = PropertySectionFilters.transformSelection(toTest);
		return transformed instanceof Identity;
	}
}


Therefore, we can now set PropertySectionFilters$IdentityFilter as the Implementation class of that added custom filter for our tab. That’s it with gmfgen customization itself.

Now let’s go into our propsheet framework. If you have checked the latest graphdef.gmfgen, you should find a second root node, Property Section Container. This is our model to let you describe custom widgets to fill your referenced tab and access features from your domain metamodel.

Note : If you have no Property Section Container second root, you can now use our new feature for “Adding extension models” for gmfgens, available from the context menu of gmfgen. It should create that second root for you, when you locate propsheet.ecore and select PropertySectionContainer to instantiate.

So now locate that second Property Section Container root, and add one more Custom Property Section child node. You can set the name for your section, if you like (I have used Generated Name, similar to other tabs). There is one main thing is to be done next. You should specify our Custom Property Tab with “Name” name, created above, as it’s Gen Tab. Thus you make a reference for genmodel entity, which will let our template customization know that the class, generated by that entity, should use our joint propsheet description instead of a plain table one.

NewCustomPropertySection.png

GenTabForNewCustomPropertySection.png

There is still one hack left, so you have to make one more custom tuning, unfortunately. This thing is going to be removed in the nearest future, but at the moment (GMF2.0M6/RC0) you can’t go without it. So, please, open templates/aspects/xpt/propsheet/Utils.ext extension file and add the ID of your Custom Property Tab (as far as I remember, I have used “genLabel” for our “Name” one) to the list of custom tabs IDs in the isGeneratedTab method at line 27. Therefore, the isGeneratedTab should look like this:


boolean isGeneratedTab(gmfgen::GenCustomPropertyTab tab) :
"genLayout" == tab.iD || "genStyles" == tab.iD || "genLabel" == tab.iD
;


Well, that’s all with the difficulties. Now only fun is left. To our “Generated NameCustom Property Section we can add graphical widgets to make it look as interesting as your imagination can make it up. So let’s play with it a little. I have added Group widget with the TextField (Note, not the plain “Text” one!) widget inside. For convenience, I have given them names, you can do this if you like, too. Besides, if you want to provide some friendly label for your users, you should add a Text element, with the help of which you will be able to turn the label completely off, or providing some custom extended label, that couldn’t be pulled out of the domain metamodel. I have added such Text child for my Group added, and specified “Identity Parameters”.

GroupAndTextFieldWidgets.png

Well, for now I think that there is enough graphics, and we can go into taking care of interaction with model. At the moment our widgets know nothing about the source from where they could take initial values or save modified ones. So there is not too much use in the code being generated so long. And it is time to breath some life into them.

We have a Text Field, so it is naturally to suppose that it’s value is provided by some metamodel feature of EString type. To use this feature to be source of values you should simply add String Value Model Element to the widget and locate your feature from the “Feature” list in the property sheet. For our case I have added String Value to the Name Text Field, and chosen “name : EStringFeature for it.

TextFieldStringValueModelElement.png

Secondly, let’s tell templates the concrete metamodel type we are going to operate within this tab. Actually, we have already provided this information with the help of Custom filter for the Custom Property Tab Name, so this is actually a little duplication of information. But the way we have done this in a filter I like less, so it is doubtful which one is to be improved. So to tell the target metatype for the tab we should add Model Mediator to Custom Property Section or any Group element. Why should it be available for any Group element widget, you may wonder. Actually, Model Mediator element is highly used by our customized templates to provide model-operating code. Group widget is logically used in two different senses, as a graphical widget (SWT Group(expandable=false) or FormsUI ExpandableComposite (expandable=true) if it doesn’t contain explicit Text element with Create Label set to false, and plain Composite otherwise), and as well a grouping element for referenced model features. Now we need to specify the metaclass to which the structural feature we have used in String Value Model Element belongs. So we add Model Mediator element and select Identity classifier from the list available for its Cast property.

GroupModelMediatorCast.png

OK. I think that is enough for the first iteration. And it is more interesting to take a look at the result now. Let’s “Generate diagram code” and run the editor. Look! It does work indeed. :)

RuntimeEditorWithName.png

Small tutorial. Part 2. Widgets concepts.

Small tutorial. Part 3. Model elements concepts.