Skip to content

Tag: geometry

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

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.