Alle Beiträge von Marco

Executive Partner @ MEDEVIT OG Partner @ MEDBITS GmbH

Horizontal extending the application model editor

With this commit the functionality to extend the Application model editor is augmented to allow for horizontal extension of its elements. So what does this mean?

Lars describes in his tutorial how to vertically extend the application model, that is, how to add additional model elements and provide a respective editor for it. But what if I want additional editing capabilities to already existing model elements like e.g. the command element?

This is where the new extension point org.eclipse.e4.tools.emf.ui.editors.editorTab comes into play. The following image shows an example of the current usage within the Écrit project:

horizontal extension point with and without
horizontal extension point with and without

We added the possibility to augment existing model elements with additional documentation artifacts – but this will become part of another blog (series) 😉

Back to the extension point. In order to use it you have to first extend this new extension point, directing it to a class extending org.eclipse.e4.tools.emf.ui.common.AbstractElementEditorContribution:

editorTab EP
editorTab EP

This class may look like

import org.eclipse.core.databinding.observable.value.WritableValue;
import org.eclipse.core.resources.IProject;
import org.eclipse.e4.tools.emf.ui.common.AbstractElementEditorContribution;
import org.eclipse.e4.ui.model.application.commands.MCommand;
import org.eclipse.emf.databinding.EMFDataBindingContext;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.swt.widgets.Composite;

public class blaClass extends AbstractElementEditorContribution {

@Override
public void createContributedEditorTab(Composite arg0,
EMFDataBindingContext arg1, WritableValue arg2, EditingDomain arg3,
IProject arg4) {
// create the editor tab in here
}

@Override
public Class<?> getContributableTo() {
return MCommand.class;
}

@Override
public String getTabLabel() {
return "myNewTab";
}
}

The getContributableTo denotes to what model elements the editorTab will be added (this is determined as you returned Class must be instanceof).

If you want to have a look at a more specific example, take a look at the Écrit implementation of the extension point.

Questions, comments? 🙂

Exporting model element ids

In order to address model elements out of the application model itsef, and out of contributing classes, the resp. model element id is used. During development you often run into errors because of wrong id strings.

To mitigate this problem a new action, called  Export Model Ids is now available within the e4 tooling starting with this build.

Popup-Menu Command Export Element Id

On execution it selects all the element ids available within the application model, and presents it to the user:

Export Id Handler Dialog

In this table you see the type of element, the static key it is gonna have in the resulting java class, and the original id. Currently the key is built out of the element type and the element id.

After execution you should find a java file called AppModelId.java, probably containing some errors due to you using duplicate ids, such as in the following image:

ExportIdHandler OutputClass AppModelId.java

There are several things I would like to change to this feature, but it seems a good start – thanks a lot to Wim for the feedbacks and reviews!

Things I would like to add/change in the future

  • make the output class, package and project selectable (currently this would introduce too much dependencies)
  • care for double occuring ids
  • make subtrees of the application model exportable (currently the whole app model ids are exported)
  • perform automatically configurable update of the target file(s)
  • remove dependency to org.eclipse.jdt.core

If you have any other feedback or comments, please put them on here!

Programmatically load an Application.e4xmi

In case you were wondering or struggling, just like me, how one could possibly load an Application.e4xmi file out of a standalone Java application, here goes some code for you 🙂

import org.eclipse.e4.ui.internal.workbench.E4XMIResourceFactory;
 import org.eclipse.e4.ui.model.application.MApplication;
 import org.eclipse.e4.ui.model.application.impl.ApplicationPackageImpl;
 import org.eclipse.emf.common.util.URI;
 import org.eclipse.emf.ecore.resource.Resource;
 import org.eclipse.emf.ecore.resource.ResourceSet;
 import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;

public class LoadAppModel {

private static ResourceSet resourceSet = new ResourceSetImpl();

public static void main(String[] args) {
 ApplicationPackageImpl.init();
 URI uri = URI
 .createURI("file:///Users/marco/git/pharmacy_at/at.medevit.ecrit.pharmacy_at.application/Application.e4xmi");

resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap()
 .put("e4xmi", new E4XMIResourceFactory());

Resource res = resourceSet.getResource(uri, true);
 MApplication app = (MApplication) res.getContents().get(0);
 System.out.println(app.getElementId());
 }
 }

res.unload();

Be sure to include all the required bundles, especially in the OSGI context.

Update I just came up to a nasty problem: If you repeatedly iterate your application model, while modifying it, you need to be sure to unload the model each time you are done, otherwise lazy loading will not pick up the changes, as the model is already loaded.

To depict this I added the unload method to the code sample.

 

Synchronising stateful items … [part1]

I’ve been banging my head some time now (which can be seen in Bug 397249) on the problem of sychronizing stateful Eclipse 4 application model items with the code.

Wait, let me set the scene first: The Items I am talking about are either Direct or Handled, Menu or Tool, Items added to either a Menu or a Toolbar in the application model. And by stateful I mean the requirements of Items of type Check or Radio to have their state synchronized with the state of the application.

Statefullness requires a Command connection

Overall stateful usage of items is bound to being connected with a Command, hence all items of type Direct are generally not considered for stateful usage. They should be used with check type only, for one shot execution of whatever you might deem necessary.

I, however, see a feasible way to use them in Type.Check which might be handy to you. In order to update the state of a Type.CHECK Direct*Item, simply use the @CanExecute annotation for a method in your contribution_uri class like this:

@CanExecute
public boolean canExecute(MItem element) {
  element.setSelected(false);
  return true;
}

@CanExecute is called everytime your element is to be shown. It allows you to update the availability of your action according to your settings, and you may also use it to update the state.

Using Direct*Items is good for smaller tasks, but one must not forget, that using this element the model has to access the implementing class to query the state. This may lead to lazy plug-ins being started just to gather the information about the availability resp. state.

Stateful Handled*Item

In order to use Handled*Items, a method (not in the code meaning but literal) is required to initialize the state of your Type.CHECK and Type.RADIO items at startup to the state of your code.

Let’s consider this for both Type.CHECK and Type.RADIO. Lets fix an example of a viewer (yes, just like this SWT TableViewer example) showing a set of Persons being either male or female. A person may also be married, single or widowed.

The Type.CHECK items in the filter will be the boolean representation of showOnlyMale in Handler, which sets it into the state to show only male persons.

The Type.RADIO items will allow us to show married, single or all persons. Here we have three contribution items which together form a radio group.

It is important that the items allowing us to select the states will be present more than once but connected to the same command. The following image depicts this:

filterCommand

The code is implemented in the Handler part, while the model is being represented by all none code parts, that is the Command and the multiple ContributionItems.

One may set the isSelected feature of the Contribution items within the application model, they are, however, not being synced to the state of the Handler (i.e. the Filter in our example) and vice versa (how should they, Eclipse does not know about the connection).

So first the question arises, whether the model should synchronize to the code, or the code to the model for this cases?

Dynamic menu contributions

Bug 389063 introduced dynamic menu items within the Eclipse 4 application model. Today Paul Webster pushed the commit to platform.ui so it is ready to show starting with tonights integration build or the upcoming Kepler M4.

But what is it, and how to use it? During development I started a sample project on called at.descher.eclipse.bug389063 that is the first to take usage of the new feature. It is accessible on my github repository.

Generally, dynamic menu contributions are added to a menu just like other elements of the form HandledMenuItem or DirectMenuItem. But instead of representing only one element they can be instantiated dynamically by anything your code wants it to show. This is similar to the dynamic menu contribution one could add in Eclipse 3.x using the org.eclipse.ui.menus extension point.

Corresponding to the Eclipse application model you now have to insert a respective menu:DynamicMenuContribution element, an example is shown in the following code snippet:

<children xsi:type="menu:DynamicMenuContribution"
       xmi:id="_JTeEkAp4EeK8ULSwuUCzow" elementId="at.descher.dmc.0"
       label="irrelevantLabelWillNotBeShown"
       contributionURI="bundleclass://at.descher.eclipse.bug389063/
        at.descher.eclipse.bug389063.dynamic.DynamicMainMenuContribution" />
 

Here one can see the reference to the contributionURI which is the class responsible to provide the Dynamic Menu Elements. There are two new annotations available which are evaluated within such contribution classes:

  • @AboutToShow the method carrying this annotation is called when the menu is about to open
  • @AboutToHide the method carrying this annotation is called when the menu is about to close

In order to provide an example I take an excerpt of the respective methods from the class DynamicMainMenuContribution class:

@AboutToShow
public void aboutToShow(List<MMenuElement> items) {
 MDirectMenuItem dynamicItem = MMenuFactory.INSTANCE
   .createDirectMenuItem();
  dynamicItem.setLabel("Dynamic Menu Item (" + new Date() + ")");
  dynamicItem
    .setContributorURI("platform:/plugin/at.descher.eclipse.bug389063");
  dynamicItem
    .setContributionURI("bundleclass://at.descher.eclipse.bug389063/
         at.descher.eclipse.bug389063.dynamic.DirectMenuItemAHandler");
items.add(dynamicItem);

In @AboutToShow an empty list, namely items gets injected. It is to be populated by the developer. The above example shows the addition of a simple MDirectMenuItem which is handled by the DirectMenuItemAHandler class.

Caution Do not put code with a long execution time within this method, as this directly blocks the opening process of the menu, and may look to the user as though the system crashed.

Providing an @AboutToHide method is optional, if one wants to say so, if however one has a reason to use it, the framework takes care about injecting the list populated during @AboutToShow into this method. So the following example shows that the list is not empty, and uses the @AboutToHide annotated method to simply increase a counter.

@AboutToHide
public void aboutToHide(List<MMenuElement> items) {
 System.out.println("aboutToHide() items-size: " + items.size());
 addSecond = !addSecond;
}

There does not yet exist support for the Application Model Editor, but I am working on it. As soon as there is news, I’ll present it here 🙂

Remark Recently I found out about two problems using this dynamic contribution, I already filed the respective Eclipse Bugs in 398866 and 398865.

[388402] SWT OS X List bug

Null Pointer ExceptionDuring several innacuretaly determinable situations we had sudden crashes of Elexis during work. These however were only occuring on OS X.

After some research I found out that the bug is caused by a NPE in the SWT List element every time one removed the last element of the list. I filed a respective bug on the Eclipse Bugtracker

Now I found the reason for this stuff to happen and it is entirely due to the MouseDown on the MenuItem entry not being followed by a MouseUp event. If you are interested in a sample application to demostrate the bug take a look at https://github.com/col-panic/generic-stuff

The bug was finally tracked down, and a patch was created according to my findings from Silenio Quarti – NICE!