Skip to content

Creating an OPM GEF Editor – Part 18: Snapping to Grid and to Geometry

Last updated on 2014-09-07

Previous Tutorial: Creating an OPM GEF Editor – Part 17: How to Define Container Edit Parts.

As a finishing touch to our editor, we will now add snapping functionality to our editor. This will probably be the last tutorial I’ll be writing for some time since I have now a working editor that can be used for my purposes. Only if I find some new GEF features that have not been covered here they will be added. But the development of my OPM editor with continue and you are always invited to check the repository for new versions.

  1. For how snapping is implemented, it looks like an undocumented feature, but it is something that I ADORE in editors, so why not use it? and the implementation is really easy. First, we have to add a new Policy to all the container nodes (OPD, Thing) called SnapFeedbackPolicy. As usual this is done in the createEditPolicies method:
    	@Override 
    	protected void createEditPolicies() {
    		installEditPolicy(EditPolicy.LAYOUT_ROLE, new OPMContainerXYLayoutPolicy());
            installEditPolicy("Snap Feedback", new SnapFeedbackPolicy());
    	}
    
        @Override
        protected void createEditPolicies() {
            super.createEditPolicies();
            installEditPolicy(EditPolicy.DIRECT_EDIT_ROLE, new OPMThingDirectEditPolicy());
            installEditPolicy("Snap Feedback", new SnapFeedbackPolicy());
        }
    
  2. Second thing we need to do is adapt these classes to SnapToHelper instances, which is a GEF provided class that helps create the snap functionality. We have to do this again twice in the OPMObjectProcessDiagramEditPart and OPMThingEditPart classes (Hm… looks like a good place to start refactoring in the future to remove duplicate code):
        /**
         * Currently the class only adapts to create a {@link SnapToHelper}
         * when the editor is in snapping mode (either to grid or to shapes).
         */
        @Override public Object getAdapter(Class key) {
            if (key == SnapToHelper.class) {
                List<SnapToHelper> helpers = new ArrayList<SnapToHelper>();
                if (Boolean.TRUE.equals(getViewer().getProperty(SnapToGeometry.PROPERTY_SNAP_ENABLED))) {
                    helpers.add(new SnapToGeometry(this));
                }
                if (Boolean.TRUE.equals(getViewer().getProperty(SnapToGrid.PROPERTY_GRID_ENABLED))) {
                    helpers.add(new SnapToGrid(this));
                }
                if(helpers.size()==0) {
                    return null;
                } else {
                    return new CompoundSnapToHelper(helpers.toArray(new SnapToHelper[0]));
                }
            }
            return super.getAdapter(key);
        }	
    

    the same implementation works in the OPMThingEditPart.

  3. Now we have to register the snap actions in the editor:
        @Override
        protected void configureGraphicalViewer() {
            super.configureGraphicalViewer();
            getGraphicalViewer().setEditPartFactory(new OPMEditPartFactory());
            getActionRegistry().registerAction(new ToggleGridAction(getGraphicalViewer())); 
            getActionRegistry().registerAction(new ToggleSnapToGeometryAction(getGraphicalViewer()));        
        }
    

    and add the actions to the toolbar:

        @Override
        protected void buildActions() {
            addRetargetAction(new UndoRetargetAction());
            addRetargetAction(new RedoRetargetAction());
            addRetargetAction(new DeleteRetargetAction());
            addRetargetAction(new RetargetAction(GEFActionConstants.TOGGLE_GRID_VISIBILITY, GEFMessages.ToggleGrid_Label, IAction.AS_CHECK_BOX));   
            addRetargetAction(new RetargetAction(GEFActionConstants.TOGGLE_SNAP_TO_GEOMETRY, GEFMessages.ToggleSnapToGeometry_Label, IAction.AS_CHECK_BOX));
        }
    
        @Override
        public void contributeToToolBar(IToolBarManager toolBarManager) {
            super.contributeToToolBar(toolBarManager);
            toolBarManager.add(getAction(ActionFactory.UNDO.getId()));
            toolBarManager.add(getAction(ActionFactory.REDO.getId()));
            toolBarManager.add(getAction(ActionFactory.DELETE.getId()));
            toolBarManager.add(getAction(GEFActionConstants.TOGGLE_GRID_VISIBILITY));
            toolBarManager.add(getAction(GEFActionConstants.TOGGLE_SNAP_TO_GEOMETRY));		
        }
    
  4. That is all that is needed!. Fire your editor and see the nice blue lines helping you snap your figures:

As usual, I hope this short explanation has helped you in your work. If you have any questions/suggestions, don’t hesitate to leave a comment.

Next Tutorial: Creating an OPM GEF Editor – Part 19: Displaying Tooltips.

Published inProgramming

5 Comments

  1. Olexandr Olexandr

    Hi there. Great tutorials for me. But I cannot change grid size, have any ideas?

    • Olexandr Olexandr

      I founded it!
      getGraphicalViewer().setProperty(SnapToGrid.PROPERTY_GRID_SPACING, new Dimension(50,50));

      • admin admin

        Exactly. That is what I also found in Google

  2. After I’ve added Grid and SnapToGeometry buttons the sizes of undo redo buttons changed to much bigger sized. Have you experienced the same problem?

    • Yea, I had this problem… I think it happens because these buttons only handle pictures correctly. Tried debugging the eclipse UI, but things get really complicated there :-(. I think the solution is to set a picture for the buttons. Check the Github repository’s latest version, since I think my current implementation is working OK.

Leave a Reply

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