Friday, April 13, 2012

Decorating GEF figure using EditPolicy

In GMF there is a nifty DragDropEditPolicy that allows you to decorate EditPart's figure by changing background color thus indicating to the user that he is hovering over particular figure. I wanted to use this in my GEF editor, but unfortunately this policy does not exist in GEF.

To make use of this policy I made my plugin depend on import org.eclipse.gmf.runtime.diagram.ui.editpolicies and extended DragDropEditPolicy with my own

public class DesignerDragDropEditPolicty extends DragDropEditPolicy {
 private Label connectionLabel;
 private PolylineConnection relationFigure;
 private DesignerEditor editor;
 private Image image;

 public DesignerDragDropEditPolicty() {
  connectionLabel = new Label();
  connectionLabel.setOpaque(false);
  image = DesignerUIPlugin.getDefault().getImageRegistry().get(ImageConstants.DROP_ICON);
  connectionLabel.setIcon(image);
  
 }
 
 @Override
 // remove icon when edit policy is done
 public void eraseTargetFeedback(Request request) {
  if(relationFigure != null){
   if(relationFigure.getChildren().contains(connectionLabel)){
    relationFigure.remove(connectionLabel);
   }
  }
 }
 
 // add icon on filtered edit part. Remove it when another edit part is hovered over.
 public void showTargetFeedback(Request request) {
  if(request instanceof CreateRequest){
   editor = (DesignerEditor) DesignerUtil.getActiveDesignerTab();
   Point location = ((CreateRequest)request).getLocation();
   EditPart part = editor.getViewer().findObjectAt(location);

   if(part instanceof RelationEditPart){
    relationFigure = ((RelationEditPart)part).getConnection();
    relationFigure.add(connectionLabel, new MidpointLocator(relationFigure, 0));
    relationFigure.repaint();
   }
   else{
    if(relationFigure != null){
     if(relationFigure.getChildren().contains(connectionLabel)){
      relationFigure.remove(connectionLabel);
     }
    }
   }
  }
 }
}


Instead of changing background of the figure as DragDropEditPolicy does I did something different. Whenever user passes inside an EditPart, in my case it's a relation, I put an icon signifying that in this case an object can be dropped onto existing connection an be created in the middle of the relation. I could have put a label saying "Drop here", but I think icons work better than words and after you get used to seeing a particular label with words it gets annoying.

Notice that in showTargetFeedback I filter out EditPart that I am interested in, so here code can be added to add different behavior for other parts.

Blogger Syntax Highliter