Vainolo's Blog

Archive for the ‘GEF’ tag

Creating an OPM GEF Editor – Part 26: Activating Tools from the Context Menu

leave a comment

Previous tutorial: Creating an OPM GEF Editor – Part 25: Showing Feedback to the User

Usability is very important when creating user interfaces, adn having to click every time in a different tool in the OPP palette to create different model entities made the experience of creating a new diagram very cumbersome. The diagram canvas is relatively large, and having to move the mouse all the time to the palette took simply too much time. There are some ways to solve this problem, and one of them is using the context menu to enable these tools. As I already showed how we can create actions in the context menu, this was just a problem of how to enable the tools when the action is triggered. As it turned out, this was not very complicated.

First, let’s create all the plumbing: we need to create an Action, register it in the editor, and add it to the context menu. The OPMCreateObjectAction is an empty action that just defines the minimum needed for an action, without doing anything:


import org.eclipse.gef.Request;
import org.eclipse.gef.ui.actions.WorkbenchPartAction;
import org.eclipse.ui.IWorkbenchPart;


public class OPMCreateObjectAction extends WorkbenchPartAction {

  public static final String ID = "CreateObject";
  public static final String REQUEST = "CreateObject";

  private final Request request;
  private CreationTool tool;

  public OPMCreateObjectAction(IWorkbenchPart part) {
    request = new Request(REQUEST);
    setText("Create Object");

  public Request getRequest() {
    return request;

  public void run() {

  protected boolean calculateEnabled() {
    return true;

Now we add this action to the editor in the OPMGraphicalEditor class, inside the createActions() function:

protected void createActions() {
  // lots of code up here
  IAction action = new OPMCreateObjectAction(this);
  // some more code down here

And add it to the context menu in the OPMGraphicalEditorContextMenuProvider class, inside the buildContextMenu() function:

public void buildContextMenu(IMenuManager menu) {
  // lots of code up here
  IAction action = getActionRegistry().getAction(OPMCreateObjectAction.ID);
  menu.appendToGroup(GEFActionConstants.GROUP_EDIT, action);
  // some more code down here…

You can start your editor now and see that the action is already in the context menu, but clicking on it does nothing (as expected).

Making the tool available from the action turned out to be a simple thing. We just need to create an instance of the tool and set it as the active tool of the editor’s EditDomain. Inside the run() function in the OPMCreateObjectAction class, I added the following code:

public void run() {
  OPMGraphicalEditor editor = (OPMGraphicalEditor) getWorkbenchPart();
  CreationTool tool = new CreationTool(new OPMObjectFactory(editor.getIdManager()));;

And voilà! When you click on the action in the context menu, the tool to create a new Object will be activated! Note that I had to expose the EditDomain of the editor that is originally protected to get this done, and this may not be the best practice, but for the first iteration, it works pretty well. There are also some more optimizations we can do, like create the tool once and not every time the action is executed, but I leave this to you as a homework :-).

Enabling the creation of links from the context menu had an added requirements – if the context menu is activated from an element (Object or Process), we should be able to use this element as the source of the link if it is a valid link source. The problem that I found here is that there is no simple way to know what is the point where the context menu was initiated, and getting the mouse location when the action is triggered is not good since this will give us the location of the mouse where the context menu item is located, which may be very different from the original location where the context menu was invoked.

I didn’t really solve this but did a workaround – if an element is selected when the context menu is invoked (and from my tests, when you invoke the context menu on top of an element it gets selected), I take the center point of this element and simulate a right-button mouse down event on the tool. This is how the run() function looks like in this case:

public void run() {
  OPMGraphicalEditor editor = (OPMGraphicalEditor) getWorkbenchPart();
  if(editor.getGraphicalViewer().getSelectedEditParts().size() == 1) {
    OPMProcessEditPart selection = (OPMProcessEditPart) editor.getGraphicalViewer().getSelectedEditParts().get(0);
    Event e = new Event();
    e.button = 1;
    e.stateMask = 0;
    e.widget = editor.getGraphicalViewer().getControl();
    Rectangle constraints = ((OPMProcess) selection.getModel()).getConstraints();
    e.x = constraints.x + constraints.width / 2;
    e.y = constraints.y + constraints.height / 2;
    tool.mouseDown(new MouseEvent(e), editor.getGraphicalViewer());

After having implemented this, I don’t understand why I didn’t do this before. Creating a model takes me half the time now.

As always, you can find the latest and greatest version of the code at Github. For this tutorials, check the OPMCreate*Action classes in the package of the project.

Written by vainolo

May 6th, 2015 at 10:11 pm

Posted in Thoughts

Tagged with , , , ,

Eclipse Draw2D Layouts Reference Card

leave a comment

FlowLayout (source)

Lays out the children a row or a column, wrapping the row/column when no more space is available.

GridLayout (source)

Lays out the children in a grid. The name of this layout is deceiving, because while it sounds like you could instantiate this grid to have a number of rows and columns and then set the figures giving for the figure a specific row and column, what the layout actually allows you to do is set the number of columns (rows) and then the figures are added sequentially to the next column (row) and after all columns (rows) are filled, a new row (column) is created. You can set some information on how each element is laid out, like alignment, spanning more than one column, etc.

XYLayout (source)

This layout gives you full control, by making you decide where you want to put every figure. With control comes responsibility (and more code).

BorderLayout (source)

Lays out the figures in 5 locations: Top, Bottom, Left, Right, and Center. Only one figure can be located in each location. The bounds given to each figure are based on the figure’s preferred size. The central figure get’s the space remaining after all other figures are laid out – it can both grow and shrink depending on how much space is left.

ToolbarLayout (source)

Arranges the figures in one column/row. It tries to insert all child figures into its client area, up to reducing them to their minimum size, but not less than this.

StackLayout (source)

The children of the figure are placed one on top of the other, with the first child added located at the bottom.

DelegatingLayout (source)

This layout expects a Locator to be passed as the child figure’s constraint. At layout time, it delegates to the Locator to perform the layout.

Enhanced by Zemanta

Written by vainolo

March 21st, 2013 at 12:48 pm

Creating an OPM GEF Editor – Part 25: “Smart” Multi-line Text Figure


Previous tutorial: Creating an OPM GEF Editor – Part 24: Showing Feedback to the User

One of the problems with visual programming languages is layout – you can stay endless hours just arranging the figures in the diagram without any real changes in the program, just to “make it look better”. This is a complete waste of time. For textual languages, it is a standard practice to have code auto-formatters that format the code every time you save. There are even some extremists who consider badly formatted code as having errors (if you are interested in the subject, there are programs like CheckStyle and Sonar to check coding standards, among others. If you use a good another tool and find it helpful, please leave me a note).

Anyway, my solution to this problem is simple: make the layout part of the language, so that it is not “secondary information”. This means that the developer cannot change the layout without changing the meaning of the program. And this also means that the language UI has to be very smart. For example, an OPP process is displayed as an ellipse, with the name of the process inside the ellipse. This could be shown in a number of ways:

Capture2 Capture1 capture4 Capture3

So the developer has a problem – he has to decide how to resize his ellipse in the “best way” possible (which will definitely be different from the “best way” of all other programmers).

My solution: don’t let the programmer decide (at least not directly), but have each model element decide on its size, based on pre-defined configuration. It took me some days to get this to work, and I had to dig and debug the GEF Logic example a couple of times, but finally I managed. I needed to do the following things: 1. calculate how large is the text; 2. calculate the desired width of the the text using a pre-determined width to height ratio (See my question on ux stackexchange regarding this ration); and 3. calculate the final size of the text after resizing it to the calculated width. The last step is needed because the text may actually end narrower because we only want to have new lines when there is a break in the text (spaces, commas, etc.). Draw2d has a component that knows how to do this (called TextFlow) but I couldn’t manage to find a way to calculate the height… I tried to use getPreferredSize() on the TextFlow after setting its size, bounds, etc, but didn’t work. And then I found it: I had to pass -1 as the desired height to the getPreferredSize() method so it calculated it alone!

So now the solution is simple: calculate the size of the text in one line (using the TextUtilities class). Calculate the area that is used by the text and from this derive the desired width, using the width to height ratio. And last, ask the FlowPage to calculate it’s preferred size using this width and a height of -1. I created a new class that does just this:

package com.vainolo.draw2d.extras;

 * Copyright (c) 2012 Arieh 'Vainolo' Bibliowicz
 * You can use this code for educational purposes. For any other uses
 * please contact me:

import org.eclipse.draw2d.TextUtilities;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.text.FlowPage;
import org.eclipse.draw2d.text.ParagraphTextLayout;
import org.eclipse.draw2d.text.TextFlow;

import com.vainolo.draw2d.extras.translate.JDraw2dToDraw2dTranslations;
import com.vainolo.jdraw2d.HorizontalAlignment;

 * A figure with a {@link TextFlow} that "smartly" calculates its preferred size,
 * using a provided width to height ratio.
public class SmartLabelFigure extends FlowPage {
  private final TextFlow textFlow;
  private double ratio;

   * Create a new smart label with the given width to height ratio (width = ratio * height)
   * @param ratio
   *          ratio to use when calculating the smart size of the label.
  public SmartLabelFigure(double ratio) {
    this.ratio = ratio;

    textFlow = new TextFlow();
    textFlow.setLayoutManager(new ParagraphTextLayout(textFlow, ParagraphTextLayout.WORD_WRAP_HARD));


  public void setText(String text) {

  public String getText() {
    return textFlow.getText();

  public void setRatio(double ratio) {
    this.ratio = ratio;

  public double getRatio() {
    return ratio;

   * Calculate the best size for this label using the class's width to height ratio.
   * This is done by calculating the area that the text would occupy if it was in only
   * one line, then calculate a new width that would give the same area using the
   * width to height ratio, and finally it sends this width to the {@link FlowPage}'s
   * {@link FlowPage#getPreferredSize(int, int)} method which calculates the real
   * height using line breaks.
   * @return A close match to the size that this figure should have to match
   *         the required width to height ratio.
  public Dimension calculateSize() {
    Dimension lineDimensions = TextUtilities.INSTANCE.getStringExtents(textFlow.getText(), getFont());
    double area = lineDimensions.width() * lineDimensions.height();
    double width = Math.sqrt(area / ratio) * ratio;
    return getPreferredSize((int) width, -1);

  public void setHorizontalAlignment(HorizontalAlignment hAlignment) {

(Note: I’m using here some special classes that I am creating in order to port the draw2d project outsize of eclipse. I’ll write
more about this in a future post).

So there it is, now the programmer can’t resize the figures, not matter how hard he tries. And the size is calculated automatically.
Using a ratio of 2, the example above looks something like this:


And here is another example:


The code for this class (and more goodies to come) can be found here and my new jdraw2d library (in progress) can be found here.

Update: the FlowPage stores a kind of “cache” of the last 3 saved layouts, so my implementation didn’t give the correct results sometime. Thankfully,
invalidate() clears this cache. The code was updated to mach this.

Next tutorial: Creating an OPM GEF Editor – Part 26: Activating Tools from the Context Menu

Written by vainolo

March 5th, 2013 at 2:11 am

%d bloggers like this: