ONJava.com    
 Published on ONJava.com (http://www.onjava.com/)
 See this if you're having trouble printing code examples


Eclipse Plugins Exposed, Part 2: Simple GUI Elements

by Emmanuel Proulx
03/30/2005

The way to write American music is simple. All you have to do is be an American and then write any kind of music you wish. -- Virgil Thompson

In the same vein, the way to write Eclipse plugins is simple too. You have to write an application and "attach" it to Eclipse. But like music, you first have to learn a lot of things before you can write a masterpiece. So let's get started.

In this article we'll discuss a few simple GUI elements:

As examples of these, we'll modify slightly our existing plugin, and write a utility class that we'll need down the road.

Extension Points

One can't just add widgets to Eclipse's user interface anywhere. It has to be done at specific, named, documented places. These are called extension points. In a basic Eclipse installation, there are hundreds of extension points available. Plugins themselves can publish new extension points. Let's have a look at the list. Open Invokatron's plugin.xml file and go to the Extensions tab. The items shown in the All Extensions tree list are the different widgets of your plugins, categorized by the extension points in which they appear. For example, the Invokatron Editor is inside an Editor (org.eclipse.ui.editor) extension point. Figure 1 shows the tab in question.

Figure 1
Figure 1. Extensions tab

Now press the Add button. A list (shown in Figure 2) appears.

Figure 2
Figure 2. New extension wizard, list of extensions

Scroll up and down this list to see the many extension points available. You'll notice that there are two kinds of extension points: those with extension templates (identified by the plus-sign icon), and those without. Most of the often-used extension points come with templates to help us developing extensions. The one selected in Figure 2, Action Set, has a template named "Hello World" action set. When you select a template, a short description appears. The next page asks for the parameters to the template.

Related Reading

Eclipse
By Steve Holzner

Now close the wizard and go back to the Extensions tab. Select the Invokatron Editor. You'll remark in this tab the information that we entered in the wizard for the Invokatron Editor, in the last article. Normal extensions need a unique identifier (Id field), a name for display (Name field), and the extension point where it belongs (Point field). Extensions created from templates (like the Invokatron Editor) need more parameters. Extension points without a template need more information, as well, but it must be entered in the text editor.

Adding a Toolbar Button

Now that we know what extension points are, let's add an extension. The first one we're going to add is a toolbar button. This button will invoke the New Invokatron wizard we've created.

There are three steps in adding a toolbar button:

  1. Declare a new extension.
  2. Augment the declaration with specific tags.
  3. Write the action delegate class.

1. Declare a new extension

We already know how to do this. Simply go back to the plugin.xml editor, under the Extensions tab. Click Add. Toolbar buttons fall under the org.eclipse.ui.actionSets extension point. Don't use the template. Click Finish directly. Enter the following for this new action:

Go to the tab plugin.xml. Eclipse added a new section to this file.

2. Augment the declaration with specific tags

This new extension is a bit naked. Let's add tags under here. How do you know which tags are allowed? You can right-click on elements in the All Extensions tree, and go to the menu New; this will give you a list. Or you can look in the Eclipse documentation under Action Sets.

Here we see that inside of the <extension> tag we can put a single <actionSet> tag. This can contain zero or more <menu> tags, followed by zero or more <action> tags, and an optional <description> tag. But the most important tag is <action>. This can describe both toolbar buttons and menu items. (We'll discuss the <menu> tag later on.)

Below is a snippet of XML code for the toolbar button we're going to add. The new code is in bold type. We will dissect this code right after.


<extension id="NewInvokatronAction"
         name="New Invokatron Document Action"
         point="org.eclipse.ui.actionSets">
  <actionSet id="invokatron.actionSet"
        label="Invokatron Actions"
        visible="true">
    <action id="invokatron.wizard.RunWizardAction"
          toolbarPath="org.eclipse.ui.workbench.file/new.ext"
          icon="icons/InvokatronIcon16.gif"
          tooltip="Starts the New Invokatron Document Wizard."
          class="invokatron.wizard.RunWizardAction">
    </action>
  </actionSet>
</extension>

All of this is also available graphically in the plugin.xml editor, but we're looking at the XML to be able to see the full text of the fields. The <actionSet> tag shown here has only one action. An action is an object that represents an item in a menu or a button in a toolbar. Action attributes are too many to list here, but they are all documented in the online help. The most interesting attributes are:

About Toolbar Paths

A toolbar path indicates where to add a toolbar button. Since anyone can create toolbars, and sometimes a button can contain sub-items, we refer to this location with a hierarchical list of identifiers. Here's a list of often-used toolbars, with their paths:

If you provide the toolbar ID without a marker ID, your button will be added in a new toolbar right next to this one. Creating toolbars is as simple as using a new toolbar name. This new toolbar will then be available to add on the Eclipse GUI. You will sometimes see plugins using the toolbar path "Normal." This is the old naming convention. Using this in Eclipse 3 will create a new toolbar named "Normal." If you create a new toolbar ID, your toolbar is added after the File toolbar.

Notice the New group marker of the File toolbar. This is where we'll add our button. Since the marker ID is new.ext, the complete path is:

org.eclipse.ui.workbench.file/new.ext

3. Write the action delegate class

The last step is to write a bit of Java to implement the action. This class is called an action delegate.

package invokatron.wizard;

public class RunWizardAction extends Action 
    implements IWorkbenchWindowActionDelegate {
    /** Called when the action is created. */
    public void init(IWorkbenchWindow window) {
    }

    /** Called when the action is discarded. */
    public void dispose() {
    }

    /** Called when the action is executed. */
    public void run(IAction action) {
        InvokatronWizard wizard= new InvokatronWizard();
        Shell shell =
          PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
        WizardDialog dialog= new WizardDialog(shell, wizard);
        dialog.create();
        dialog.open();
    }

    /** Called when objects in the editor are selected or deselected. */
    public void selectionChanged(IAction action, ISelection selection) {
    }
}

Adding a Menu Item

As you may have guessed adding a menu item is almost the same as adding a toolbar button. You also have to declare an extension (the same kind), augment the declaration with specific tags (the same tags), and write an action class (the same class). The main difference is with the declaration of the extension. Here's how extension XML code looks like for a menu item without a corresponding toolbar button:


<extension id="NewInvokatronAction"
         name="New Invokatron Document Action"
         point="org.eclipse.ui.actionSets">
  <actionSet id="invokatron.actionSet"
        label="Invokatron Actions"
        visible="true">
    <action id="invokatron.wizard.RunWizardAction"
          label="New Invokatron"
          menubarPath="file/new.ext"
          icon="icons/InvokatronIcon16.gif"
          tooltip="Starts the New Invokatron Document Wizard."
          class="invokatron.wizard.RunWizardAction">
    </action>
  </actionSet>
</extension>

The label attribute contains the text that will be displayed in the menu item. Keyboard shortcuts are represented by "&" which is written &amp; in XML. And now for an example of a combined menu item and toolbar button:


<extension id="NewInvokatronAction"
         name="New Invokatron Document Action"
         point="org.eclipse.ui.actionSets">
  <actionSet id="invokatron.actionSet"
        label="Invokatron Actions"
        visible="true">
    <action id="invokatron.wizard.RunWizardAction"
          label="New Invokatron"
          menubarPath="file/new.ext"
          toolbarPath="org.eclipse.ui.workbench.file/new.ext"
          icon="icons/invokatronPicture.gif"
          tooltip="Starts the New Invokatron Document Wizard."
          class="invokatron.wizard.RunWizardAction">
    </action>
  </actionSet>
</extension>

Menus are a little bit different than toolbars. There's only one "level" of toolbars but there's a whole hierarchy of menus. This is why it is possible to declare menus along with actions. Menus are listed inside of the <actionSet> tag, above <action> tags. They have the following syntax:


    <menu id="unique.ID"
          <!-- New menu at the top-level. The menubarPath
              for actions inside this menu is: Special -->
          path="Special" 
          label="This is a parent menu item.">
      <!-- Optional, the menubarPath for actions after
         this separator is: Special/BelowBar -->
      <separator name="BelowBar"> 
    </menu>
About Menubar Paths

A menubar path indicates where to add a menu item. We refer to this location with a hierarchical list of identifiers. Here's a list of often-used menubars, with their paths, and public group markers (when available):

If you provide the menubar ID without a marker ID, your menu item will appear right next to this menubar. If you create a new menubar ID, your menubar is added between the Project and Run menus.

Message to Eclipse developers: Please use more consistency for toolbar and menubar IDs, and marker locations.

Notice the New group marker of the File menu. This is where we'll add our menu item. Since the marker ID is new.ext, the complete path is:

file/new.ext

The Result

Many other features are available in Action Sets, including shortcut keys, state buttons, hovering icons, help context, window toolbars, etc. And Action Sets is just a single kind of extension point among the dozens that are documented. So what we saw is just the tip of the iceberg. But at least it gives you a good idea of how extension points works. The 1. 2. 3. procedure we saw is always good.

Before we move on to wizard customizations, Figure 3 shows what the new toolbar button and menu item look like:

Figure 3
Figure 3. New menu item and toolbar button

Standard Dialogs

Eclipse comes with a full range of standard dialogs and an easy way to create custom dialogs. Many standard dialogs are provided by the class org.eclipse.jface.dialogs.MessageDialog. This has many static methods to create standard dialogs. The following lists some of the standard dialogs available.

Type of dialog Creation method Equivalent in Swing
Confirmation (Message, question mark icon, OK, and Cancel buttons) MessageDialog.openConfirm( Shell parent, String title, String message) Returns true if the user has clicked OK, false otherwise. JOptionPane.showConfirmDialog(...) passing the optionType JOptionPane.OK_CANCEL_OPTION
Error (Message, error icon, OK button) MessageDialog.openError( Shell parent, String title, String message) JOptionPane.showMessageDialog(...) passing the messageType JOptionPane.ERROR_MESSAGE
Informational (Message, information icon, OK button) MessageDialog.openInformation( Shell parent, String title, String message) JOptionPane.showMessageDialog(...) passing the messageType JOptionPane.INFORMATION_MESSAGE
Yes/No question (Message, question mark icon, Yes and No buttons) MessageDialog.openQuestion( Shell parent, String title, String question) Returns true if the user has clicked Yes, false otherwise. JOptionPane.showConfirmDialog(...) passing the optionType JOptionPane.YES_NO_OPTION
Warning (Message, warning icon, OK buttons) MessageDialog.openWarning( Shell parent, String title, String message) JOptionPane.showMessageDialog(...) passing the messageType JOptionPane.WARNING_MESSAGE

One may think that the JOptionPane class offers more flexibility than MessageDialog when it comes to standard dialogs. But ultimately, with MessageDialog's constructor and custom dialogs you can do almost anything. The only feature missing in MessageDialog, which JOptionPane has, is direct message formatting in HTML. This can be worked around with customized dialogs.

Dialog Helper Class

Now that we know our options, let's create the dialogs that we need for Invokatron. There are two areas that necessitate dialogs:

Let's create a new utility class that will host these dialogs. Create the folder Invokatron/src/invokatron/helper and make a new class named DialogHelper.

The first method in this class is for the confirmation of code overwriting. Here it is:


public static boolean openOverwriteDialog(Shell parent) {
    return MessageDialog.openConfirm(parent,
        "Confirmation",
        "You are about to overwrite your class. " +
        "Are you sure you want to continue?");
}

This is very simple, we just create a regular confirmation dialog. The input dialog is another matter: MessageDialog doesn't have an input field. We could just create a new dialog class, maybe a subclass of Dialog. We could also subclass MessageDialog and override its createCustomArea() method to add the input field. But there's a simpler way.

We'll use the InputDialog class!


public static String openInputDialog(
      Shell parent,
      String title,
      String question,
      String initialValue) {

    InputDialog dlg = new InputDialog(
            parent,
            title,
            question,
            initialValue,
            null); //This is an optional validation class
    dlg.open();

    if(dlg.getReturnCode()!=Window.OK) //Didn't click on OK!
        return null;

    return dlg.getValue();
}

Our dialog helper class is done. You can look at the dialogs in Figure 4. We will make use of it in the next issues of the series.

Figure 4
Figure 4. Dialogs

The Eclipse Symphony

Eclipse is like music; once you learn how to use some of the available instruments, you can write yourself a symphony. Today we've briefly seen two categories of instruments: extension points and dialogs. In the next article, we'll talk about how to enter and save the state of our editor.

Resources

Emmanuel Proulx is an expert in J2EE and Enterprise JavaBeans, and is a certified WebLogic Server 7.0 engineer. He works in the fields of telecommunications and web development.


Return to ONJava.com.

Copyright © 2009 O'Reilly Media, Inc.