How to create and customize boundary items in Eclipse GMF

In this quick “how-to” I will describe the steps required to put a boundary element in your Eclipse GMF editor. I assume you have already created your model. Here is ours :

As you can see, we have an activity object that can contain boundary events. We want to put a boundary event on the border of an activity.

  1. Gmfgraph
  2. First a figure must be defined for your model element. This is done in the gmfgraph file. It is important to set an "Affixed Parent Side", setting it will determine if the element is put at the boundary of the parent element or not. Here we set it to SOUTH in consequence the element will be positioned below the parent.

  3. Gmfmap
  4. Next, in the gmfmap, a child reference is set on the node where we want the object to be fixed as any other node. Here our boundary element is

    We now have a boundary event that will be displayed to the south of our activity.

  5. Custom border item locator
  6. However, we want our boundary event to be centered on the border and not next to it. This is where our custom border item locator comes in!

    We will customize GMF templates to replace the default BorderItemLocator. If you don’t know how to customize templates take a look at this post.

    The edited template is located in /impl/diagram/editparts/NodeEditPart.xpt. In this file we have modified the addFixedChild method.

    «REM»For affixed children use a custom borderItemLocator«ENDREM»
    «FOREACH getSideAffixedChildren(self) AS child-»
    if (childEditPart instanceof «child.getEditPartQualifiedClassName()») {
    org.eclipse.gmf.runtime.diagram.ui.figures.BorderItemLocator locator
    = new org.bonitasoft.studio.common.gmf.ActivityBorderItemLocator(getMainFigure(),
    org.eclipse.draw2d.PositionConstants.«child.preferredSideName»);
    getBorderedFigure().getBorderItemContainer()
    .add(((«child.getEditPartQualifiedClassName()») childEditPart).getFigure(), locator);
    return true;
    }
    «ENDFOREACH-»
    We create this custom BorderItemLocator:

    [cc lang=“java”]
    public class ActivityBorderItemLocator extends BorderItemLocator {

    /**

    • Use to “middle overlap” the affixed child
      */
      private static final int halfSizeOfAfffixedChild = 8;

    public ActivityBorderItemLocator(IFigure parentFigure) {
    super(parentFigure);
    setBorderItemOffset(new Dimension(halfSizeOfAfffixedChild, halfSizeOfAfffixedChild));
    }

    public ActivityBorderItemLocator(IFigure mainFigure, int preferredSide) {
    super(mainFigure, preferredSide);
    setBorderItemOffset(new Dimension(halfSizeOfAfffixedChild, halfSizeOfAfffixedChild));
    }

    /**

    • Get an initial location based on the side. ( choose first sixth part of the side for SOUTH or call super)
    • @param side
    • the preferred side of the parent figure on which to place this
    • border item as defined in {@link PositionConstants}
    • @return point
      */
      protected Point getPreferredLocation(int side, IFigure borderItem) {
      if (side == PositionConstants.SOUTH) {
      Rectangle bounds = getParentBorder();
      int parentFigureWidth = bounds.width;
      int parentFigureHeight = bounds.height;
      int parentFigureX = bounds.x;
      int parentFigureY = bounds.y;
      int x = parentFigureX;
      int y = parentFigureY;
      /Play with this for modify the horizontal position on the activity Figure/
      x += parentFigureWidth / 6;
      y = parentFigureY + parentFigureHeight - getBorderItemOffset().height;
      return new Point(x, y);
      } else {
      return super.getPreferredLocation(side, borderItem);
      }
      }
      }
      [/cc]

    And that’s it! We have our boundary event where we want it.

  7. Moving issue
  8. We have another issue though, since our boundary item is extending Element, which is our base eClass. Moving boundary elements from a task to a pool is semantically possible but we don't want that! We create a CustomDragDropEditPolicy to forbid this move: This class must extend org.eclipse.gmf.runtime.diagram.ui.editpolicies.DragDropEditPolicy [cc lang="java"] @Override protected Command getDragCommand(ChangeBoundsRequest request) { if(/* condition on request to detect invalid move */){//disallow to move to another process return UnexecutableCommand.INSTANCE; } return super.getDragCommand(request); } [/cc] We then install this edit policy as EditPolicyRoles.DRAG_DROP_ROLE: [cc lang="java"] editPart.installEditPolicy(EditPolicyRoles.DRAG_DROP_ROLE, new CustomDragDropEditPolicy()); [/cc]