e4 – Some more news from the modeltooling


Fragment Tooling

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 …).

Here’s a screenshot of a running application:

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:


This dialog helps you finding the appropriate parent-id which acts as the container for your contributed element.

Find the correct attribute:


This dialog helps you to find the correct attribute-name into which your element is stored in.

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.

Here a similar new ID-dialog has been added allowing you to search for ids you’d like to import:

If we now reopen the Command Dialog we are able to select the command we want to connect our binding to:

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.

This entry was posted in e4. Bookmark the permalink.

6 Responses to e4 – Some more news from the modeltooling

  1. Miles Parker says:

    Hi Tom,

    “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.”

    That’s not true actually. For example, you can control where views are placed with:

    It’s not different really from the API. And actually since you can’t get any information from the API at that point anyway it is a better place to do it since you’re defining all of your views in the plugin.xl as it is. Where you run into issues is with other more complex API stuff.

    Which brings m to an important question. What’s the role / capability for programmatic control of views and layouts with an e4 application? It’s very important for my app to be able to add multiple instances of the views where and when I want them — this has involved a fair amount of Workbench hackery but it all works at least. What I have never been able to do is cause views to move from one place to another based on changes in my environment (a running simulation model losing or something) the best I can do is simply change perspectives and that generally works pretty well. I’m hoping that the e4 design does not assume a rigid design time presentation?

    cheers, and following this all with interest,

    Miles

    • tomeclipsedev says:

      Miles yes. You are right you can control where to place it but the main layout of a perspective is defined in Java, very complex nesting is not possible at all. Now to your question about programmatic controling. You as a user has access to the workbench-model at runtime and modify it at any time, showing/hiding views, … Naturally you can do everything you can with 3.x (if not the compat layer would not be possible) but you get much more and don’t have to hack any workbench stuff any more.

      I’ll try to write up a blog how to hide, show views and modify the workbench-model (which is a live model did I mention that?) at runtime, so modification of the model can be made at any point in time (design time and runtime)

      • Miles Parker says:

        OK, yes I see the distinction you are making. And it is extremely limiting — not to mention the point that many people have made that the distinction between editors and views is pretty artificial and requires an incredible amount of code / configuration changes should you wish to move from one to another.

        And yes the question I was asking was essentially wether the model was live or not.. I’m very excited to hear that it is! In fact, wow, that gives me a ton of ideas — a lot of my view stuff from that perspective could essentially be seen as sort of a M2M transformation. Good stuff.

  2. Miles Parker says:

    Hmmm.. didn’t seem to like my blockquote, here’s the perspecitve example in plain text..

  3. Björn Voß says:

    Hello Tom,

    maybe this is not the correct location for that question, but I am going to ask you anyway. Actually, I am trying to contribute HandledMenuItems from different bundles using model fragments into the menu of my base model at a specific position. Therefore I thought about using the “Position in List” attribute is the correct way to do this. But if I try to set the position by entering e.g. “2” for an item, i get the error message “Not a valid list position” while application starts and the menu item is not at the expected position. Could you please explain the using of the “Position in List” attribute or explain how to set an item at a specific position, if using the “Position in List” attribute is not the correct way to do this.

    thanks

    Björn

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.