As you might see with the number of posts. I’ve been hacking a lot my ModelTooling-Editor and so after having talked about the latest features 3 days ago, I have some more news today.
I’ve spend half of my yesterdays evening improving the ModelFragment-Tooling.
For those not familiar with e4 and the workbench model this might not be clear so I’ll explain in short what ModelFragements are:
I guess most of you are familiar with 3.x and know how you contribute a view, editor, command, menu, … you use the matching extension point (e.g. org.eclipse.ui.views). The definition of the Meta-Model (or better said the various attributes you can define for a contributed elements) are defined in various .exsd files who can only use IDs to connected to each other (e.g. to connect a Menu-Contribution to a Command and Handler to a Command).
A view contribution looks like this:
<?xml version="1.0" encoding="UTF-8"?> <?eclipse version="3.4"?> <plugin> <extension point="org.eclipse.ui.views"> <view class="org.eclipse.e4.demo.contacts.views.ListView" id="ContactsView" name="ContactsView" restorable="true"> </view> </extension> </plugin>
All those extension definitions are collected when your 3.x Application (the Eclipse SDK is nothing more than that) is started and converted in so called descriptors, stored in registries (e.g. IViewRegistry) which can be accessed like this:
IViewDescriptor desc = PlatformUI.getWorkbench().getViewRegistry().find("ContactsView");
and used internally to make up workbench, with its ViewParts, EditorParts, Menus, … but the descriptors have no reference to each other (e.g. the menu item descriptor contributed to a views menu has no idea about view-descriptor, …) their relationship is a purely virtual one made up inside the workbench and defined through ids (so there’s no picture I can show you at this point).
The situation in an e4-Application is completely different. The workbench itself defines a concrete model which defines the relation ship between the different parts of the system and this model is used by the workbench to make up your complete application (from the command to the handler to the parts (=editor and view) to the menu item …).
The problem we are now having is how this running application is constructed. For small applications who are not created out of many different individual parts one can define the application up-front and simply start up with this monolithic model but this would obviously not work for things like the Eclipse SDK which is made of from many different more or less independent OSGi-Bundles.
Now you could think that this is exactly where the well known extension points from 3.x could come into play because they allow to make up an application from those independent bundles and to some extend you are right this is possible or better exactly what the compat layer is doing. It takes all you extension points and makes up an application model like this:
But this is not ideal because now that the application itself defines already the Meta-Model (attributes, containments, references, …) its not making sense to have 2 systems who define how the contributed data looks like beside the fact that you’ve never been able to contribute e.g. the layout of a perspective but this information has been made up in IPerspectiveFactory using Java-Code.
So we came up with another solution we named ModelFragments who themselves use the the Meta-Model which was used to define the workbench model itself. All you need to know is one extension point named “org.eclipse.e4.workbench.model” which allows you to contribute fragments to an existing base model.
The problem from the tooling side of this that you need to reference elements in the base model using IDs and the tooling need to help you looking them up in the available base models and other fragments (yes fragments can point to other fragments :-). So what’s needed is a way to look up and find all of those models in a workspace and provide the user with a dialog to select the appropriate element he’d like to reference when contributing.
There are 2 types of references used in our new contribution story:
Referencing a parent element:
This is the more obvious use case where you want to contribute a childelement to an existing container. Take a look at the following Model:
If we’d like to contribute a Part-Element below the selected stack “all” we need to do is to reference the parent element and define below which feature we’d like to contribute our Part-Fragment.
At this moment the new tooling I added helps you finding the correct place and element you’ll want to contribute to.
Find the correct parent id:
Find the correct attribute:
Referencing another element:
The second area where you need to reference is more subtle but very important also. An example for it is that you’d like to contribute a keybinding for a command not defined by yourself but someone else. Here’s the base model where our keybinding should take place:
You see that we need to contribute a (Key)Binding below the BindingTable with the Id “org.eclipse.ui.contexts.dialogAndWindow”. So we do exactly what we did above and come up with the following:
but this is not enough a KeyBinding needs to reference the command the keybinding is connected to! Remember what I said above how the model internally is working. It is using Java-References and not those weak ID-References from 3.x. So looking at the Keybinding-Editor we notice that we need to somehow reference the command instance but apparently the fragment doesn’t hold such a reference.
So we are in trouble now that e4 is not using id-references but strong ones (EMF people now might say that we should use cross-references between models but without going into detail is not solving our problem – you can read in depth discussion on this bug).
The solution we use is that we allow you to create imports inside the model fragment which uses IDs to reference the real elements definition which gives you a instance of the element at design time and at runtime when the model is put together those import-elements are replaced by the real ones.
ToBeRendered and Visible-Attributes
Eric Moffatt pointed me to the fact that we the model editor is not able to edit 2 important fields of our UI-Elements (visible/toBeRendered) and promised an extra bonus when they they show up in gray in the tree on the left.
Drag&Drop and C&P between files
I think don’t have to explain this. You can now drag and drop and copy and paste elements from model files to model files. This is quite nice e.g. to add imports without using the Find-Dialog.