About Me

My photo
I'm project manager of a software development team at www.researchspace.com. I've been developing bioinformatics software for the last 9 years or so, and I'm hoping to share some of the experience and knowledge I've gained with Eclipse RCP, Java web app development and software development in general on these blogs.

Wednesday 24 September 2008

Selection actions in GEF

In this blog, I will demonstrate how to use Selection Actions in GEF. These are actions which can be enabled via the context menu, dependent on the items selected in the editor. They are specifically useful for performing operations on selected edit parts, via their getSelectedObjects() method.

System setup
I'm using Windows XP and Eclipse Ganymede (3.4), but Eclipse 3.3 or 3.2 should work as well and the examples should be platform independent. To follow this tutorial, download the GEF-SDK complete, and unzip the example plugins into the 'Drops' directory of your Eclipse IDE ( or just the plugins directory if you're running Eclipse 3.3 or earlier). Restart Eclipse, and create a Shapes Plugin Project in Eclipse by
File->New->Example->GefPlugins->ShapesExample.

At the end of this stage you should have the shapes example plugin project in your workspace, with source code.

Assumed knowledge of reader
This tutorial is designed for a developer who has read the 'Shape Diagram Editor' tutorial available from the GEF website, and has some knowledge of the basic GEF framework but is looking to extend their knowledge.

Selection Action Example

Our example task will be to create an action that when run, will select, and scroll to, the source or target of a connection. This action is useful in complex diagrams with long connections where the connection endpoints are outside the viewable area of the diagram. This action will just be enabled when a single connection is selected.

Step 1: Creating the action

First of all, lets create a new package for editor actions, org.eclipse.gef.examples.actions, in the Shapes Example plugin, and in it create a new class, SrcSelectAction that extends org.eclipse.gef.ui.actions.SelectionAction. After creation, the class will look like this

package org.eclipse.gef.examples.actions;

import org.eclipse.gef.ui.actions.SelectionAction;
import org.eclipse.ui.IWorkbenchPart;

public class SrcSelectAction extends SelectionAction {
public SrcSelectAction(IWorkbenchPart part) {
super(part);
}

protected boolean calculateEnabled() {
// TODO Auto-generated method stub
return false;
}

}


For now, add the following lines:

public class SrcSelectAction extends SelectionAction {
// an identifier for the action
public static final String ID="shapes.tutorial.SrcSelectAction";
public SrcSelectAction(IWorkbenchPart part) {
super(part);
setId(ID); // sets ID
setText("Select link src"); // sets text displayed in the menu
setToolTipText("Focus on link source");
}
....
}




Later, we'll add an implementation for the calculateEnabled method and override
public void run().
Now however we need to make sure the action is registered with the editor and is created properly.

Step 2 - Registering the action with the editor.
The GraphicalEditor class provided by GEF creates some standard actions for
Copy, Delete etc using the method

protected void createActions()

In the ShapesEditor class, we can override this method to create our own actions:

protected void createActions() {
super.createActions(); // important else we won't get the default actions!
IAction action = new SrcSelectAction(this);
getActionRegistry().registerAction(action);
getSelectionActions().add(action.getId());
}


Now we will add the action to the editor context menu:

In the class ShapesEditorContextMenuProvider add the following lines to buildContextMenu(IMenuManager menu)

IAction action = getAction(SrcSelectAction.ID);
if (action.isEnabled()){
menu.appendToGroup(GEFActionConstants.GROUP_COPY, action);
}


This code will add the action to the context menu if the result of the action's calculateEnabled() method returns true.

Step 3 - Enabling the action

Now let's go back implement the calculateEnabled() method in SrcSelectAction:

protected boolean calculateEnabled() {
// we only want enabled if is single selection
if(getSelectedObjects().size() !=1
|| (!(getSelectedObjects().get(0) instanceof ConnectionEditPart))){
return false;
}
// and we want the model to be a Connection object.
ConnectionEditPart cep = (ConnectionEditPart)getSelectedObjects().get(0);
if(cep.getModel() instanceof Connection ){
return true;
}
return false;

}



Step 4 - Running the action

In the run() method we need to get the connection source and invoke methods on the edit part's viewer to select and reveal it.

public void run() {
/*this method is only called if calculate enabled() returns true
* so we know its a ConnectionEditPart
*/
ConnectionEditPart cep = (ConnectionEditPart)getSelectedObjects().get(0);
/*Any EditPart can access its viewer
*/
EditPartViewer viewer = cep.getViewer();

/* Deselect an existing selection */
viewer.deselectAll();

/* Flush this */
viewer.flush();

/* Select the source edit part */
viewer.select(cep.getSource());

/* If the source Edit part is off screen, this will scroll to it.
viewer.reveal(cep.getSource());
}




Step 5 Deploying the plugin

  1. Export the plugin using File->Export->Plugins->DeployablePlugins and Fragments
  2. Quit Eclipse
  3. Replace the existing Shapes Example plugin with your deployed version
  4. Restart Eclipse
  5. Try to create a new example shapes diagram.


Now, try creating 2 shapes and a link between them. If you select the connection and get the context menu you should see the 'Select Link Src' action in the menu. If you select this action then the link source will be selected.

Step 6 Summary

In this blog I've described how to create a simple SelectionAction in GEF. This example can easily be extended to any other action involving a selection, for example selecting all edit parts with a particular model type.

Thanks for reading this, in the next blog I'll talk about my approach to testing actions in GEF.

2 comments:

darkhie said...

Thank You very much :) A great and simple tutorial on adding custom action to context menu :)

Hreno said...

Thanks for this, it was very useful! :)

I hope you'll continue with your blog.