ActionSets tutorial

Writing your first Action

Background

The concept of an action in the workbench very closely reflects that of an action in Eclipse. We use actions to define to the workbench a particular action that a user can take on the workbench. As such, we use the idea of actions to define toolbar items.

There are 2 types of action set contributions in the workbench; one for the workbench itself, and one for a particular view part. In addition you can just create and add actions directory to a view part. This tutorial explains how to do all three.

Workbench Action Contributions

Workbench actions are contributed to the workbench via the org.karora.moomba.ui.actionSets identifier. For complete details refer to Action Sets - org.karora.moomba.ui.actionSets.

A simple action must implement the org.karora.moomba.ui.IWorkbenchWindowActionDelegate interface.
Here's one I prepared earlier:

public class SimpleAction implements IWorkbenchWindowActionDelegate {
	/**
	 * We will cache window object in order to
	 * be able to provide parent shell for the message dialog.
	 * @see IWorkbenchWindowActionDelegate#init
	 */
	public void init(IWorkbenchWindow window) {
	}

	/**
	 * We can use this method to dispose of any system
	 * resources we previously allocated.
	 * @see IWorkbenchWindowActionDelegate#dispose
	 */
	public void dispose() {
	}

	/**
	 * The action has been activated. The argument of the
	 * method represents the 'real' action sitting
	 * in the workbench UI.
	 * @see IActionDelegate#run
	 */
	public void run(IAction action) {
	}

	/**
	 * Selection in the workbench has been changed. We 
	 * can change the state of the 'real' action here
	 * if we want, but this can only happen after 
	 * the delegate has been created.
	 * @see IActionDelegate#selectionChanged
	 */
	public void selectionChanged(IAction action, ISelection selection) {
	}
}
  • init - is called by the workbench on initialisation of the action. The method can cache the window object for later use.
  • dispose - is called when the action is removed from the workbench.
  • run - is called when the action has been activated (i.e. by a user click).
  • selectionChanged - is called when a selection event is fired in the workbench (not implemented).

For our simple example we are going to display a message dialog. For this we will need the WorkbenchWindow so that we can obtain the parent shell for the dialog.
Therefore, we need to cache the window:

private IWorkbenchWindow window;

public void init(IWorkbenchWindow window) {
	this.window = window;
}

And then add the code to display the message dialog to the run method:

public void run(IAction action) {
	MessageDialog.openInformation(
		window.getWindow(),
		"Simple Action",
		"This is an example of a simple workbench action",
		null);
}

Now that we have done this, we need to add the following to the plugin.xml file in the top-level directory of the bundle:

<extension
      point="org.karora.moomba.ui.actionSets">
   <actionSet
         label="Sample Action Set"
         visible="true"
         id="example.actionSet">
      <action
            label="Simple Action"
            icon="image/simple.png"
            class="com.my.project.ui.action.SimpleAction"
            tooltip="Simple Action example"
            toolbarPath="sampleGroup"
            id="com.my.project.ui.action.SimpleAction">
      </action>
   </actionSet>
</extension>

All you have to do is now deploy the built bundle into your Equinox runtime and you should see the action as a toolbar button in the Workbench window.

View Part Action Contributions

View Part actions are contributed to a view part via the org.karora.moomba.ui.viewActions identifier. For complete details refer to View Actions - org.karora.moomba.ui.viewActions.

A simple action must implement the org.karora.moomba.ui.IViewActionDelegate interface.
Here's one I prepared earlier:

public class SimpleAction implements IViewActionDelegate {
	/**
	 * We will cache window object in order to
	 * be able to provide parent shell for the message dialog.
	 * @see IViewActionDelegate#init
	 */
	public void init(IViewPart view) {
	}

	/**
	 * The action has been activated. The argument of the
	 * method represents the 'real' action sitting
	 * in the workbench UI.
	 * @see IActionDelegate#run
	 */
	public void run(IAction action) {
	}

	/**
	 * Selection in the workbench has been changed. We 
	 * can change the state of the 'real' action here
	 * if we want, but this can only happen after 
	 * the delegate has been created.
	 * @see IActionDelegate#selectionChanged
	 */
	public void selectionChanged(IAction action, ISelection selection) {
	}
}
  • init - is called by the workbench on initialisation of the action. The method can cache the window object for later use.
  • run - is called when the action has been activated (i.e. by a user click).
  • selectionChanged - is called when a selection event is fired in the workbench (not implemented).

Again, for our simple example we are just going to display a message dialog. We will need the IViewPart so that we can obtain the parent shell for the dialog.
Therefore, we need to cache the view part:

private IViewPart view;

public void init(IViewPart view) {
	this.view = view;
}

And then add the code to display the message dialog to the run method:

public void run(IAction action) {
	MessageDialog.openInformation(
		view.getSite().getShell(),
		"Simple Action",
		"This is an example of a simple view part action",
		null);
}

Now that we have done this, we need to add the following to the plugin.xml file in the top-level directory of the bundle:

<extension
      point="org.karora.moomba.ui.viewActions">
   <viewContribution
         id="viewAction.viewContribution1"
         targetID="org.karora.moomba.demo.ui.view.DemoActionView">
      <action
            label="Simple Action"
            icon="image/simple.png"
            class="com.my.project.ui.action.ViewSimpleAction"
            tooltip="Simple Action example"
            toolbarPath="sampleGroup"
            id="com.my.project.ui.action.ViewSimpleAction">
      </action>
   </viewContribution>
</extension>

The important difference to note here between the workbench action contribution and the view part action contribution is the viewContribution targetID attribute which specifies the ID of the target view part to where the action is to be added.

View Part Actions

Of course you can also simply add actions to a view part without the extension point contribution mechanism. This can be done in a number of different ways depending largely on your requirements, and the following is just one example.
This example adds an action to the view part toolbar in the createPartControl method of a view part.

Action simpleAction = new SimpleAction() {
	public void run(IAction action) {
		MessageDialog.openInformation(
			getSite().getShell(),
			"Simple Action",
			"This is an example of a simple action",
			null);
	}
};
simpleAction.setToolTipText("Simple Action");
simpleAction.setImageDescriptor(new ResourceImageReference("image/simple.png"));

getViewSite().getActionBars().getToolBarManager().add(simpleAction);

More complicated actions

Fundamentally there are 4 different types of actions.

  • push
  • radio
  • toggle
  • pulldown

The pulldown action can not be contributed to a view part using the org.karora.moomba.ui.viewActions extension.
In the case of a contribution, the value of the 'state' attribute determines which action will be created. With the exception of the pulldown action, they should all implement either org.karora.moomba.ui.IWorkbenchWindowActionDelegate or org.karora.moomba.ui.IViewActionDelegate depending upon whether it is a WorkbenchWindow action or a View action. However, if the action is of type 'pulldown' then it must implement the org.karora.moomba.ui.IWorkbenchWindowPulldownDelegate.

There is no real difference between push, radio or toggle other than their resultant behaviour. However, the pulldown action is slightly different in that is has to specify a menu for the pulldown. This can be done in one of 2 ways. Either the getMenu method must be overridden to return the menu, or you can set a IMenuCreator (which effectively does the same thing)
The following is an example of how this is acheived by using the IMenuCreator interface:

existingAction.setMenuCreator(new IMenuCreator() {

	// Return the sub-menu for use in a menu
	public Menu getMenu(Menu parent) {
		Menu m = new Menu("Menu 1", new ResourceImageReference("image/smile.png"));
		m.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				MessageDialog.openInformation(
						getSite().getShell(),
						"View example drop down action",
						"Menu item 1 selected",
						null);
			}
		});
		parent.add(m);

		m = new Menu("Menu 2");
		m.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				MessageDialog.openInformation(
						getSite().getShell(),
						"View example drop down action",
						"Menu item 2 selected",
						null);
			}
		});
		parent.add(m);
		return parent;
	}

	// Return the menu for use in a toolbar drop-down action
	public Menu getMenu(Component parent) {
		return null;
	}
});

Labels